/* control_loop() is the main STCP loop; it repeatedly waits for one of the * following to happen: * - incoming data from the peer * - new data from the application (via mywrite()) * - the socket to be closed (via myclose()) * - a timeout */ static void control_loop(mysocket_t sd, context_t *ctx) { assert(ctx); assert(!ctx->done); while (!ctx->done) { unsigned int event; event = stcp_wait_for_event(sd, ANY_EVENT, NULL); /* check whether it was the network, app, or a close request */ if (event & NETWORK_DATA) { /* there was network data received */ //our_dprintf("got network data\n"); handle_cstate_est_recv(sd, ctx); } if (event & APP_DATA) { /* the application has requested that data be sent */ /* see stcp_app_recv() */ handle_cstate_est_send(sd, ctx); } if (event & APP_CLOSE_REQUESTED) { /* the application has requested that the conn be closed */ //our_dprintf("close received \n"); send_syn_ack_fin(sd, ctx, SEND_FIN, 0, 0); ctx->connection_state = CSTATE_FIN_WAIT_1; close_tcp_conn(sd, ctx); } } }
bool gsm_pwr_off( ) { u16 result_temp; //close connect... AT^SISC=0 if( !close_tcp_conn( ) ) { debug_gsm("Close connection error\r\n"); } //Check link status... AT^SISI? result_temp = check_tcp_status( ); debug_gsm("AT^SISI return %d\r\n",result_temp); if ( result_temp != 2 ) { //error, force shutdown close_tcp_conn( ); OSTimeDlyHMSM(0, 0, 1, 0); } //shutdown module ... AT^SMSO if( !shutdown_mg323( ) ) { debug_gsm("shutdown error\r\n"); OSTimeDlyHMSM(0, 0, 1, 0); shutdown_mg323( ); } else { debug_gsm("shutdown CMD ok.\r\n"); } OSTimeDlyHMSM(0, 0, 1, 0);//不能太长,否则会自动重开机 GSM_PM_OFF; my_icar.mg323.try_online_cnt = 1; my_icar.mg323.gprs_count = 0 ; my_icar.mg323.gprs_ready = false; my_icar.mg323.tcp_online = false ; my_icar.mg323.power_on = false; memset(my_icar.mg323.ip_local, 0x0, IP_LEN-1); prompt("Turn off GSM power.\r\n"); return true ; }
bool gprs_disconnect( ) { prompt("!!! Close GPRS connection !!!\t"); //close connect... AT^SISC=0 if( close_tcp_conn( ) ) { prompt("ok.\r\n"); } else { prompt("failure.\r\n"); } my_icar.mg323.tcp_online = false ; my_icar.mg323.try_online_cnt = 1 ; return true ; }
/* initialise the transport layer, and start the main loop, handling * any data from the peer or the application. this function should not * return until the connection is closed. */ void transport_init(mysocket_t sd, bool_t is_active) { context_t *ctx; int res; ctx = (context_t *) calloc(1, sizeof(context_t)); assert(ctx); generate_initial_seq_num(ctx); ctx->connection_state = CSTATE_CLOSED; ctx->send_wind = (uint8_t *) malloc(MAX_WINDOW_SIZE); memset(ctx->send_wind, 0, MAX_WINDOW_SIZE); ctx->recv_wind = (uint8_t *) malloc(MAX_WINDOW_SIZE); memset(ctx->recv_wind, 0, MAX_WINDOW_SIZE); res = open_tcp_conn(sd, ctx, is_active); /* XXX: you should send a SYN packet here if is_active, or wait for one * to arrive if !is_active. after the handshake completes, unblock the * application with stcp_unblock_application(sd). you may also use * this to communicate an error condition back to the application, e.g. * if connection fails; to do so, just set errno appropriately (e.g. to * ECONNREFUSED, etc.) before calling the function. */ stcp_unblock_application(sd); if (ctx->connection_state == CSTATE_ESTABLISHED){ control_loop(sd, ctx); } else if (ctx->connection_state == CSTATE_FIN_WAIT_1){ close_tcp_conn(sd, ctx); } else if (ctx->connection_state == CSTATE_CLOSED) { ; }else { our_dprintf("bad state in transport init"); assert(0); } /* do any cleanup here */ free(ctx->send_wind); free(ctx->recv_wind); free(ctx); }
int handle_cstate_syn_rcvd(mysocket_t sd, context_t * ctx) { int ret = 0; unsigned int event; our_dprintf("in CSTATE_SYN_RCVD\n"); event = stcp_wait_for_event(sd, NETWORK_DATA | APP_CLOSE_REQUESTED | TIMEOUT, NULL); /* check whether it was the network, app, or a close request */ if (event & NETWORK_DATA) { /* there was network data received */ size_t recd; recd = stcp_network_recv(sd, ctx->recv_wind, MAX_WINDOW_SIZE); if (recd == 0) { our_dprintf("bad network recv\n"); return -1; } struct tcphdr * tcp_packet = (struct tcphdr *) ctx->recv_wind; if (tcp_packet->th_flags & TH_ACK){ /* ack received */ if (ntohl(tcp_packet->th_ack) < ctx->sent_last_byte_acked || ntohl(tcp_packet->th_ack) > ctx->sent_last_byte_written+1){ our_dprintf("bad ack, expected %u, received %u. returning \n", ctx->sent_last_byte_sent+1, tcp_packet->th_ack); return -1; } ctx->sent_last_byte_acked = ntohl(tcp_packet->th_ack); ctx->recd_adv_window = ntohs(tcp_packet->th_win); //our_dprintf("*** got ack %u, got adv window %u\n", ctx->sent_last_byte_acked, ctx->recd_adv_window); ctx->connection_state = CSTATE_ESTABLISHED; } } if (event & APP_CLOSE_REQUESTED) { /* the application has requested that the conn be closed */ ctx->connection_state = CSTATE_FIN_WAIT_1; close_tcp_conn(sd, ctx); } return ret; }
int handle_cstate_est_recv(mysocket_t sd, context_t * ctx){ our_dprintf("* IN EST REC\n"); size_t len = sizeof(struct tcphdr) + STCP_MSS; uint8_t buff[len]; uint32_t data_len, data_index; size_t delta, recv_len, recv_packet_len; recv_len = stcp_network_recv(sd, buff, len); struct tcphdr * tcp_packet = (struct tcphdr *) buff; size_t hdr_size = tcp_packet->th_off * 4; recv_packet_len = recv_len - 4 * tcp_packet->th_off; /* check if any data was ack'd */ if (tcp_packet->th_flags & TH_ACK) { if (ntohl(tcp_packet->th_ack) < ctx->sent_last_byte_acked || ntohl(tcp_packet->th_ack) > ctx->sent_last_byte_written+1){ our_dprintf("bad ack, expected %u, received %u. returning \n", ctx->sent_last_byte_sent+1, tcp_packet->th_ack); return -1; } ctx->sent_last_byte_acked = ntohl(tcp_packet->th_ack); //our_dprintf("****got an ack: %u\n", tcp_packet->th_ack); } /* check to see if the seq number is appropriate */ if (ntohl(tcp_packet->th_seq) != ctx->recd_next_byte_expected){ //our_dprintf("unexpected seq. rec seq : %u, expected : %u\n", tcp_packet->th_seq, ctx->recd_next_byte_expected); /* if part of the data is below the seq window */ if ((ntohl(tcp_packet->th_seq) < ctx->recd_next_byte_expected) && (ntohl(tcp_packet->th_seq) + recv_packet_len > ctx->recd_next_byte_expected)){ //our_dprintf("some data salvageable\n"); /* some of the data should be salvaged */ data_len = ntohl(tcp_packet->th_seq) + recv_packet_len - ctx->recd_next_byte_expected; data_index = recv_packet_len - data_len; } else if (0) { /* placeholder for if data overflows upper bound of sliding window */ } else { //our_dprintf("bad packet\n"); return 0; } } else { data_len = recv_packet_len; data_index = 0; } uint8_t * data = buff + hdr_size; uint32_t wind_index = ((ctx->recd_last_byte_recd + 1) - ctx->initial_recd_seq_num) % MAX_WINDOW_SIZE; //our_dprintf("window index %u, data len %u\n", wind_index, data_len); //our_dprintf("received data: %s\n", data); if (wind_index + data_len > MAX_WINDOW_SIZE){ /* we're wrapping the buffer */ delta = MAX_WINDOW_SIZE - wind_index; //our_dprintf("wrapping recv buff \n"); /*copy data to ctx->buffer and send it to app */ memcpy(ctx->recv_wind + wind_index, data + data_index, delta); stcp_app_send( sd, ctx->recv_wind + wind_index, delta); memcpy(ctx->recv_wind, data + delta + data_index, data_len - delta); stcp_app_send( sd, ctx->recv_wind, data_len - delta); } else { /* we're not wrapping the buffer */ //our_dprintf("don't need to wrap, data len %d\n", data_len); /*copy data to ctx->buffer and send it to app */ memcpy(ctx->recv_wind + wind_index, data + data_index, data_len); stcp_app_send( sd, ctx->recv_wind + wind_index, data_len); } ctx->recd_last_byte_recd += data_len; ctx->recd_next_byte_expected += data_len; ctx->recd_last_byte_read += data_len; if (data_len > 0 ) { //our_dprintf("acking %u bytes\n", data_len); send_syn_ack_fin(sd, ctx, SEND_ACK, 0, ctx->recd_next_byte_expected); } else { //our_dprintf("** flags %u\n", tcp_packet->th_flags); } if (tcp_packet->th_flags & TH_FIN) { stcp_fin_received(sd); if (data_len == 0){ ctx->recd_last_byte_recd++; ctx->recd_next_byte_expected++; ctx->recd_last_byte_read++; } send_syn_ack_fin(sd, ctx, SEND_ACK, 0, ctx->recd_next_byte_expected); ctx->connection_state = CSTATE_CLOSE_WAIT; close_tcp_conn(sd, ctx); } return 0; }