/*---------------------------------------------------------------------------*/ static PT_THREAD(create_test_session(struct psock *p)) { /* * A protosocket's protothread must start with a PSOCK_BEGIN(), with * the protosocket as argument. */ PSOCK_BEGIN(p); /* * Here we define all the thread local variables that we need to * utilize. */ static RequestSession request; static AcceptSession accept; PSOCK_WAIT_UNTIL(p,PSOCK_NEWDATA(p)); if(PSOCK_NEWDATA(p)){ /* * We read data from the buffer now that it has arrived. * Using memcpy we store it in our local variable. */ PSOCK_READBUF(p); memcpy(&request,buffer,sizeof(request)); TEST_AMOUNT = (int) request.NumOfPackets; UDP_SENDER_PORT = (int) request.SenderPort; UDP_RECEIVER_PORT = (int) request.RecieverPort; /* * Prints for debugging. */ printf("Type: %"PRIu32"\n",request.Type); printf("SenderPort: %"PRIu32"\n",request.SenderPort); printf("ReceiverPort: %"PRIu32"\n",request.RecieverPort); printf("SenderAddress: %08x,%x\n",request.SenderAddress,request.SenderMBZ); printf("ReceiverAddress: %08x,%x\n",request.RecieverAddress,request.RecieverMBZ); printf("StartTime: %u\n",request.StartTime.Second); accept.Accept = 0; accept.Port = request.RecieverPort; PSOCK_SEND(p, &accept, sizeof(accept)); PSOCK_SEND(p, &accept, sizeof(accept)); } else { printf("Timed out!\n"); } state = 3; PSOCK_END(p); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(send_part_of_file(struct httpd_state *s)) { PSOCK_BEGIN(&s->sout); PSOCK_SEND(&s->sout, s->file.data, s->len); PSOCK_END(&s->sout); }
static PT_THREAD(send_file(struct httpd_state *s)) { PSOCK_BEGIN(&s->sout); char filename[HTTPD_PATHLEN]; strcpy(filename, slip_config_www_root); strcat(filename, s->filename); strcpy(s->filename, filename); s->fd = open(s->filename, O_RDONLY); if (s-> fd > 0) { do { /* Read data from file system into buffer */ s->len = read(s->fd, s->outputbuf, sizeof(s->outputbuf)); /* If there is data in the buffer, send it */ if(s->len > 0) { PSOCK_SEND(&s->sout, (uint8_t *)s->outputbuf, s->len); } else { break; } } while(s->len > 0); } close(s->fd); PSOCK_END(&s->sout); }
/* * Timesynch functionality */ static PT_THREAD(timesynch(struct psock *p)) { PSOCK_BEGIN(p); printf("TIME: %d\n",clock_time()); static TimesynchSRMsg time_pkt; memset(&time_pkt,0,sizeof(time_pkt)); PSOCK_WAIT_UNTIL(p,PSOCK_NEWDATA(p)); if(PSOCK_NEWDATA(p)){ clock_time_t t2 = clock_time(); PSOCK_READBUF(p); memcpy(&time_pkt,buffer,sizeof(time_pkt)); time_pkt.t1 = time_pkt.t1; time_pkt.t2 = t2; time_pkt.t3 = clock_time(); printf("Clock print: %u\n",clock_time()); PSOCK_SEND(p,&time_pkt,sizeof(time_pkt)); printf("Clock print: %u\n",clock_time()); printf("T1: %u\n",time_pkt.t1); printf("T2: %u\n",time_pkt.t2); printf("T3: %u\n",time_pkt.t3); } else { printf("Timed out!\n"); PSOCK_CLOSE_EXIT(p); } state = 4; PSOCK_END(p); }
// This function is going to use uIP's protosockets to handle the connection. // This means it must return int, because of the way the protosockets work. // In a nutshell, when a PSOCK_* macro needs to wait for something, it will // return from handle_connection so that other work can take place. When the // event is triggered, uip_callback() will call this function again and the // switch() statement (see below) will take care of resuming execution where // it left off. It *looks* like this function runs from start to finish, but // that's just an illusion to make it easier to code :-) int UIPClient::handle_connection(uip_tcp_appstate_t *s) { // All protosockets must start with this macro. Its internal implementation // is that of a switch() statement, so all code between PSOCK_BEGIN and // PSOCK_END is actually inside a switch block. (This means for example, // that you can't declare variables in the middle of it!) struct psock *p = &s->p; uip_userdata_t *u = (uip_userdata_t *) s->user; PSOCK_BEGIN(p); if (uip_newdata() && readyToReceive(s)) { PSOCK_READBUF_LEN(p, 0); //TODO check what happens when there's more new data incoming than space left in UIPClients buffer (most likely this is just discarded, isn't it?) dataReceived(s); } if (readyToSend(s)) { PSOCK_SEND(p, u->out_buffer, u->out_len); dataSent(s); } if (isClosed(s)) { // Disconnect. PSOCK_CLOSE(p); } // All protosockets must end with this macro. It closes the switch(). PSOCK_END(p); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(send(void)) { PSOCK_BEGIN(&s.sout); PSOCK_SEND(&s.sout, s.outputbuf, s.len); PSOCK_END(&s.sout); }
static PT_THREAD(handle_output(contiki_data_t *s)) { PSOCK_BEGIN(&s->p); if (s->state == WRITTING) { PSOCK_SEND(&s->p, s->out_buf, s->out_len); s->state = WRITE_END; process_post_synch(s->process, xively_event, s); } PSOCK_END(&s->p); }
static int handle_tcp_connection(struct psock *p, enum tcp_event_type type, struct net_buf *buf) { PSOCK_BEGIN(p); if (type == TCP_WRITE_EVENT) { NET_DBG("Trying to send %d bytes data\n", uip_appdatalen(buf)); PSOCK_SEND(p, buf); } PSOCK_END(p); }
/* * A protosocket always requires a protothread. The protothread * contains the code that uses the protosocket. We define the * protothread here. */ static PT_THREAD(handle_connection(struct psock *p)) { /* * A protosocket's protothread must start with a PSOCK_BEGIN(), with * the protosocket as argument. * * Remember that the same rules as for protothreads apply: do NOT * use local variables unless you are very sure what you are doing! * Local (stack) variables are not preserved when the protothread * blocks. */ PSOCK_BEGIN(p); /* * We start by sending out a welcoming message. The message is sent * using the PSOCK_SEND_STR() function that sends a null-terminated * string. */ PSOCK_SEND_STR(p, "Welcome, please type something and press return.\n"); /* * Next, we use the PSOCK_READTO() function to read incoming data * from the TCP connection until we get a newline character. The * number of bytes that we actually keep is dependant of the length * of the input buffer that we use. Since we only have a 10 byte * buffer here (the buffer[] array), we can only remember the first * 10 bytes received. The rest of the line up to the newline simply * is discarded. */ PSOCK_READTO(p, '\n'); /* * And we send back the contents of the buffer. The PSOCK_DATALEN() * function provides us with the length of the data that we've * received. Note that this length will not be longer than the input * buffer we're using. */ PSOCK_SEND_STR(p, "Got the following data: "); PSOCK_SEND(p, buffer, PSOCK_DATALEN(p)); PSOCK_SEND_STR(p, "Good bye!\r\n"); /* * We close the protosocket. */ PSOCK_CLOSE(p); /* * And end the protosocket's protothread. */ PSOCK_END(p); }
static PT_THREAD(SendData(struct httpd_state *s, int len, char* b)) { static int c = 0; PSOCK_BEGIN(&s->sout); f(7, "SendData___________________ ", &c); PSOCK_SEND(&s->sout, b, len); f(7, "SendData ", &c); if (s->state == STATE_OUTPUT) { s->state = STATE_WAITING; } else { // if == STATE_OUTPUT_READBACK s->state = STATE_READBACK; } PSOCK_END(&s->sout); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(send_file(struct httpd_state *s)) { PSOCK_BEGIN(&s->sout); do { /* Read data from file system into buffer */ s->len = cfs_read(s->fd, s->outputbuf, sizeof(s->outputbuf)); /* If there is data in the buffer, send it */ if(s->len > 0) { PSOCK_SEND(&s->sout, (uint8_t *)s->outputbuf, s->len); } else { break; } } while(s->len > 0); PSOCK_END(&s->sout); }
/* -------------------------------------------------------------------------- */ static PT_THREAD(handle_connection(struct psock *p)) { // So, as always let's start PSOCK_BEGIN(p); // Let's send a hello world PSOCK_SEND_STR(p, "Welcome, please type something and press return.\n"); // Let's block this thread untile a new line is received PSOCK_READTO(p, '\n'); // And what we receive, we send it back, MUAHAHA PSOCK_SEND_STR(p, "Got the following data: "); PSOCK_SEND(p, buffer, PSOCK_DATALEN(p)); PSOCK_SEND_STR(p, "Good bye!\r\n"); // Finally close the socket PSOCK_CLOSE(p); // The End... PSOCK_END(p); }
static PT_THREAD(send_data(connection_state_t* conn_state)) { uint16_t index; http_response_t* response; http_header_t* header; uint8_t* buffer; PSOCK_BEGIN(&(conn_state->sout)); PRINTF("send_data -> \n"); index = 0; response = &conn_state->response; header = response->headers; buffer = allocate_buffer(200); /*FIXME: what is the best solution here to send the data. Right now, if buffer is not allocated, no data is sent!*/ if (buffer) { index += sprintf(buffer + index, "%s %d %s%s", httpv1_1, response->status_code, response->status_string, line_end); for (; header; header = header->next) { PRINTF("header %u \n", (uint16_t)header); index += sprintf(buffer + index, "%s%s%s%s", header->name, header_delimiter, header->value, line_end); } index += sprintf(buffer + index, "%s", line_end); memcpy(buffer + index, response->payload, response->payload_len); index += response->payload_len; PRINTF("Sending Data(size %d): %s \n", index, buffer); PSOCK_SEND(&(conn_state->sout), buffer, index); } else { PRINTF("BUFF ERROR: send_data!\n"); } PSOCK_END(&(conn_state->sout)); }
static PT_THREAD(handle_mqtt_connection(mqtt_state_t* state)) { static struct etimer keepalive_timer; uint8_t msg_type; uint8_t msg_qos; uint16_t msg_id; PSOCK_BEGIN(&state->ps); // Initialise and send CONNECT message mqtt_msg_init(&state->mqtt_connection, state->out_buffer, state->out_buffer_length); state->outbound_message = mqtt_msg_connect(&state->mqtt_connection, state->connect_info); PSOCK_SEND(&state->ps, state->outbound_message->data, state->outbound_message->length); state->outbound_message = NULL; // Wait for CONACK message PSOCK_READBUF_LEN(&state->ps, 2); if(mqtt_get_type(state->in_buffer) != MQTT_MSG_TYPE_CONNACK) PSOCK_CLOSE_EXIT(&state->ps); // Tell the client we're connected mqtt_flags |= MQTT_FLAG_CONNECTED; complete_pending(state, MQTT_EVENT_TYPE_CONNECTED); // Setup the keep alive timer and enter main message processing loop etimer_set(&keepalive_timer, CLOCK_SECOND * state->connect_info->keepalive); while(1) { // Wait for something to happen: // new incoming data, // new outgoing data, // keep alive timer expired PSOCK_WAIT_UNTIL(&state->ps, PSOCK_NEWDATA(&state->ps) || state->outbound_message != NULL || etimer_expired(&keepalive_timer)); // If there's a new message waiting to go out, then send it if(state->outbound_message != NULL) { PSOCK_SEND(&state->ps, state->outbound_message->data, state->outbound_message->length); state->outbound_message = NULL; // If it was a PUBLISH message with QoS-0 then tell the client it's done if(state->pending_msg_type == MQTT_MSG_TYPE_PUBLISH && state->pending_msg_id == 0) complete_pending(state, MQTT_EVENT_TYPE_PUBLISHED); // Reset the keepalive timer as we've just sent some data etimer_restart(&keepalive_timer); continue; } // If the keep-alive timer expired then prepare a ping for sending // and reset the timer if(etimer_expired(&keepalive_timer)) { state->outbound_message = mqtt_msg_pingreq(&state->mqtt_connection); etimer_reset(&keepalive_timer); continue; } // If we get here we must have woken for new incoming data, // read and process it. PSOCK_READBUF_LEN(&state->ps, 2); state->message_length_read = PSOCK_DATALEN(&state->ps); state->message_length = mqtt_get_total_length(state->in_buffer, state->message_length_read); msg_type = mqtt_get_type(state->in_buffer); msg_qos = mqtt_get_qos(state->in_buffer); msg_id = mqtt_get_id(state->in_buffer, state->in_buffer_length); switch(msg_type) { case MQTT_MSG_TYPE_SUBACK: if(state->pending_msg_type == MQTT_MSG_TYPE_SUBSCRIBE && state->pending_msg_id == msg_id) complete_pending(state, MQTT_EVENT_TYPE_SUBSCRIBED); break; case MQTT_MSG_TYPE_UNSUBACK: if(state->pending_msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && state->pending_msg_id == msg_id) complete_pending(state, MQTT_EVENT_TYPE_UNSUBSCRIBED); break; case MQTT_MSG_TYPE_PUBLISH: if(msg_qos == 1) state->outbound_message = mqtt_msg_puback(&state->mqtt_connection, msg_id); else if(msg_qos == 2) state->outbound_message = mqtt_msg_pubrec(&state->mqtt_connection, msg_id); deliver_publish(state, state->in_buffer, state->message_length_read); break; case MQTT_MSG_TYPE_PUBACK: if(state->pending_msg_type == MQTT_MSG_TYPE_PUBLISH && state->pending_msg_id == msg_id) complete_pending(state, MQTT_EVENT_TYPE_PUBLISHED); break; case MQTT_MSG_TYPE_PUBREC: state->outbound_message = mqtt_msg_pubrel(&state->mqtt_connection, msg_id); break; case MQTT_MSG_TYPE_PUBREL: state->outbound_message = mqtt_msg_pubcomp(&state->mqtt_connection, msg_id); break; case MQTT_MSG_TYPE_PUBCOMP: if(state->pending_msg_type == MQTT_MSG_TYPE_PUBLISH && state->pending_msg_id == msg_id) complete_pending(state, MQTT_EVENT_TYPE_PUBLISHED); break; case MQTT_MSG_TYPE_PINGREQ: state->outbound_message = mqtt_msg_pingresp(&state->mqtt_connection); break; case MQTT_MSG_TYPE_PINGRESP: // Ignore break; } // NOTE: this is done down here and not in the switch case above // because the PSOCK_READBUF_LEN() won't work inside a switch // statement due to the way protothreads resume. if(msg_type == MQTT_MSG_TYPE_PUBLISH) { uint16_t len; // adjust message_length and message_length_read so that // they only account for the publish data and not the rest of the // message, this is done so that the offset passed with the // continuation event is the offset within the publish data and // not the offset within the message as a whole. len = state->message_length_read; mqtt_get_publish_data(state->in_buffer, &len); len = state->message_length_read - len; state->message_length -= len; state->message_length_read -= len; while(state->message_length_read < state->message_length) { PSOCK_READBUF_LEN(&state->ps, state->message_length - state->message_length_read); deliver_publish_continuation(state, state->message_length_read, state->in_buffer, PSOCK_DATALEN(&state->ps)); state->message_length_read += PSOCK_DATALEN(&state->ps); } } } PSOCK_END(&state->ps); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(smtp_thread(void)) { PSOCK_BEGIN(&s.psock); PSOCK_READTO(&s.psock, ISO_nl); if(strncmp(s.inputbuffer, smtp_220, 3) != 0) { PSOCK_CLOSE(&s.psock); smtp_done(2); PSOCK_EXIT(&s.psock); } PSOCK_SEND_STR(&s.psock, (char *)smtp_helo); PSOCK_SEND_STR(&s.psock, localhostname); PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl); PSOCK_READTO(&s.psock, ISO_nl); if(s.inputbuffer[0] != ISO_2) { PSOCK_CLOSE(&s.psock); smtp_done(3); PSOCK_EXIT(&s.psock); } PSOCK_SEND_STR(&s.psock, (char *)smtp_mail_from); PSOCK_SEND_STR(&s.psock, s.from); PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl); PSOCK_READTO(&s.psock, ISO_nl); if(s.inputbuffer[0] != ISO_2) { PSOCK_CLOSE(&s.psock); smtp_done(4); PSOCK_EXIT(&s.psock); } PSOCK_SEND_STR(&s.psock, (char *)smtp_rcpt_to); PSOCK_SEND_STR(&s.psock, s.to); PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl); PSOCK_READTO(&s.psock, ISO_nl); if(s.inputbuffer[0] != ISO_2) { PSOCK_CLOSE(&s.psock); smtp_done(5); PSOCK_EXIT(&s.psock); } if(s.cc != 0) { PSOCK_SEND_STR(&s.psock, (char *)smtp_rcpt_to); PSOCK_SEND_STR(&s.psock, s.cc); PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl); PSOCK_READTO(&s.psock, ISO_nl); if(s.inputbuffer[0] != ISO_2) { PSOCK_CLOSE(&s.psock); smtp_done(6); PSOCK_EXIT(&s.psock); } } PSOCK_SEND_STR(&s.psock, (char *)smtp_data); PSOCK_READTO(&s.psock, ISO_nl); if(s.inputbuffer[0] != ISO_3) { PSOCK_CLOSE(&s.psock); smtp_done(7); PSOCK_EXIT(&s.psock); } PSOCK_SEND_STR(&s.psock, (char *)smtp_to); PSOCK_SEND_STR(&s.psock, s.to); PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl); if(s.cc != 0) { PSOCK_SEND_STR(&s.psock, (char *)smtp_cc); PSOCK_SEND_STR(&s.psock, s.cc); PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl); } PSOCK_SEND_STR(&s.psock, (char *)smtp_from); PSOCK_SEND_STR(&s.psock, s.from); PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl); PSOCK_SEND_STR(&s.psock, (char *)smtp_subject); PSOCK_SEND_STR(&s.psock, s.subject); PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl); PSOCK_SEND(&s.psock, s.msg, s.msglen); PSOCK_SEND_STR(&s.psock, (char *)smtp_crnlperiodcrnl); PSOCK_READTO(&s.psock, ISO_nl); if(s.inputbuffer[0] != ISO_2) { PSOCK_CLOSE(&s.psock); smtp_done(8); PSOCK_EXIT(&s.psock); } PSOCK_SEND_STR(&s.psock, (char *)smtp_quit); smtp_done(SMTP_ERR_OK); PSOCK_END(&s.psock); }
/* * A protosocket always requires a protothread. The protothread * contains the code that uses the protosocket. We define the * protothread here. */ static PT_THREAD(connection_setup(struct psock *p)) { /* * A protosocket's protothread must start with a PSOCK_BEGIN(), with * the protosocket as argument. */ PSOCK_BEGIN(p); printf("TIME: %d\n",clock_time()); /* * Here we define all the thread local variables that we need to * utilize. */ static ServerGreeting greet; static SetupResponseUAuth setup; static ServerStartMsg start; static int i; static int acceptedMode = 1; /* * We configure the Server-Greeting that we want to send. Setting * the accepted modes to those we accept. The following modes are * meaningful: * 1 - Unauthenticated * 2 - Authenticated * 3 - Encrypted * 0 - Do not wish to communicate. */ memset(&greet, 0, sizeof(greet)); greet.Modes = 1; /* * We generate random sequence of octects for the challenge and * salt. */ for (i = 0; i < 16; i++){ greet.Challenge[i] = rand() % 16; } for (i = 0; i < 16; i++){ greet.Salt[i] = rand() % 16; } /* * Count must be a power of 2 and be at least 1024. */ //greet.Count = (1 << 12); /* * We set the MBZ octets to zero. */ for (i = 0; i < 12; i++){ greet.MBZ[i] = 0; } /* * Using PSOCK_SEND() we send the Server-Greeting to the connected * client. */ PSOCK_SEND(p, &greet, sizeof(greet)); /* * We wait until we receive a server greeting from the server. * PSOCK_NEWDATA(p) returns 1 when new data has arrived in * the protosocket. */ PSOCK_WAIT_UNTIL(p,PSOCK_NEWDATA(p)); if(PSOCK_NEWDATA(p)){ /* * We read data from the buffer now that it has arrived. * Using memcpy we store it in our local variable. */ PSOCK_READBUF(p); memcpy(&setup,buffer,sizeof(setup)); if(setup.Modes != acceptedMode){ printf("Client did not match our modes!\n"); PSOCK_CLOSE_EXIT(p); } else{ /* * We have agreed upon the mode. Now we send the Server-Start * message. */ memset(&start,0,sizeof(start)); /* * We set the MBZ octets to zero. */ for (i = 0; i < 15; i++){ start.MBZ1[i] = 0; } for (i = 0; i < 8; i++){ start.MBZ2[i] = 0; } /* * The accept field is set to zero if the server wishes to continue * communicating. A non-zero value is defined as in RFC 4656. */ start.Accept = 0; /* * Timestamp is set to the time the Server started. */ double temp; start.timestamp.Second = clock_seconds(); temp = (double) clock_time()/CLOCK_SECOND - start.timestamp.Second; start.timestamp.Fraction = temp*1000; /* * Using PSOCK_SEND() we send the Server-Start to the connected * client. */ PSOCK_SEND(p, &start, sizeof(start)); printf("Client agreed to mode: %d\n",setup.Modes); } } else { printf("Timed out!\n"); } state = 2; PSOCK_END(p); }