/* * 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); }
/*---------------------------------------------------------------------------*/ 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(handle_connection(struct psock *p)) { PSOCK_BEGIN(p); while (true) { if (PSOCK_NEWDATA(p)) PSOCK_CLOSE(p); else PSOCK_SEND_STR(p,msg); } PSOCK_END(p); }
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); }
/* * 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); }