Exemple #1
0
/*---------------------------------------------------------------------------*/
static void
acked(struct tcp_socket *s)
{
  if(s->output_senddata_len > 0) {
    /* Copy the data in the outputbuf down and update outputbufptr and
       outputbuf_lastsent */

    if(s->output_data_send_nxt > 0) {
      memcpy(&s->output_data_ptr[0],
             &s->output_data_ptr[s->output_data_send_nxt],
             s->output_data_maxlen - s->output_data_send_nxt);
    }
    if(s->output_data_len < s->output_data_send_nxt) {
      printf("tcp: acked assertion failed s->output_data_len (%d) < s->output_data_send_nxt (%d)\n",
             s->output_data_len,
             s->output_data_send_nxt);
      tcp_markconn(uip_conn, NULL);
      uip_abort();
      call_event(s, TCP_SOCKET_ABORTED);
      relisten(s);
      return;
    }
    s->output_data_len -= s->output_data_send_nxt;
    s->output_senddata_len = s->output_data_len;
    s->output_data_send_nxt = 0;

    call_event(s, TCP_SOCKET_DATA_SENT);
  }
}
Exemple #2
0
void AreaBullet::dispatch_callbacks() {
	if (!isScratched)
		return;
	isScratched = false;

	// Reverse order because I've to remove EXIT objects
	for (int i = overlappingObjects.size() - 1; 0 <= i; --i) {
		OverlappingObjectData &otherObj = overlappingObjects.write[i];

		switch (otherObj.state) {
			case OVERLAP_STATE_ENTER:
				otherObj.state = OVERLAP_STATE_INSIDE;
				call_event(otherObj.object, PhysicsServer::AREA_BODY_ADDED);
				otherObj.object->on_enter_area(this);
				break;
			case OVERLAP_STATE_EXIT:
				call_event(otherObj.object, PhysicsServer::AREA_BODY_REMOVED);
				otherObj.object->on_exit_area(this);
				overlappingObjects.remove(i); // Remove after callback
				break;
			case OVERLAP_STATE_DIRTY:
			case OVERLAP_STATE_INSIDE:
				break;
		}
	}
}
void
client_main_loop (void)
{
    int quit = 0;
    int engine_updated = 0;

    /* Set up the game */
    reset_start_time ();

    update_avail_modules (0);

    screen_full_refresh ();

    if (no_init_help == 0) {
	block_help_exit = 1;
	help_flag = 1;
	if (make_dir_ok_flag) {
	    activate_help ("ask-dir.hlp");
	    make_dir_ok_flag = 0;
	} else {
	    activate_help ("opening.hlp");
	}
    }

    /* Set speed */
#if defined (CS_PROFILE) || defined (START_FAST_SPEED)
    select_fast ();
#else
    select_medium ();
#endif
    /* Main Loop */
    do {
	int key;

	/* Get timestamp for this iteration */
	get_real_time();

	/* Process events */
#if defined (LC_X11)
	call_event ();
	key = x_key_value;
	x_key_value = 0;
#elif defined (WIN32)
	call_event ();
	key = GetKeystroke ();
#else
	mouse_update ();
	key = vga_getkey ();
#endif
	/* nothing happened if key == 0 XXX: right? */
	/* GCS: I'm not sure */
	if (key != 0) {
            process_keystrokes (key);
	}
	/* Simulate the timestep */
	quit = execute_timestep ();
    } while (quit == 0);
}
/*---------------------------------------------------------------------------*/
static void
handle_suback(struct mqtt_connection *conn)
{
  struct mqtt_suback_event suback_event;

  DBG("MQTT - Got SUBACK\n");

  /* Only accept SUBACKS with X topic QoS response, assume 1 */
  if(conn->in_packet.remaining_length > MQTT_MID_SIZE +
     MQTT_MAX_TOPICS_PER_SUBSCRIBE * MQTT_QOS_SIZE) {
    DBG("MQTT - Error, SUBACK with > 1 topic, not supported.\n");
  }

  conn->out_packet.qos_state = MQTT_QOS_STATE_GOT_ACK;

  suback_event.mid = (conn->in_packet.payload[0] << 8) |
    (conn->in_packet.payload[1]);
  suback_event.qos_level = conn->in_packet.payload[2];
  conn->in_packet.mid = suback_event.mid;

  if(conn->in_packet.mid != conn->out_packet.mid) {
    DBG("MQTT - Warning, got SUBACK with none matching MID. Currently there is"
        "no support for several concurrent SUBSCRIBE messages.\n");
  }

  /* Always reset packet before callback since it might be used directly */
  call_event(conn, MQTT_EVENT_SUBACK, &suback_event);
}
/*---------------------------------------------------------------------------*/
static void
handle_publish(struct mqtt_connection *conn)
{
  DBG("MQTT - Got PUBLISH, called once per manageable chunk of message.\n");
  DBG("MQTT - Handling publish on topic '%s'\n", conn->in_publish_msg.topic);

  DBG("MQTT - This chunk is %i bytes\n", conn->in_packet.payload_pos);

  if(((conn->in_packet.fhdr & 0x09) >> 1) > 0) {
    PRINTF("MQTT - Error, got incoming PUBLISH with QoS > 0, not supported atm!\n");
  }

  call_event(conn, MQTT_EVENT_PUBLISH, &conn->in_publish_msg);

  if(conn->in_publish_msg.first_chunk == 1) {
    conn->in_publish_msg.first_chunk = 0;
  }

  /* If this is the last time handle_publish will be called, reset packet. */
  if(conn->in_publish_msg.payload_left == 0) {

    /* Check for QoS and initiate the reply, do not rely on the data in the
     * in_packet being untouched. */

    DBG("MQTT - (handle_publish) resetting packet.\n");
    reset_packet(&conn->in_packet);
  }
}
Exemple #6
0
// Handle the back branch event. Notice that we can compile the method
// with a regular entry from here.
void AdvancedThresholdPolicy::method_back_branch_event(methodHandle mh, methodHandle imh,
                                                       int bci, CompLevel level, TRAPS) {
  if (should_create_mdo(mh(), level)) {
    create_mdo(mh, THREAD);
  }

  // If the method is already compiling, quickly bail out.
  if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh, bci)) {
    // Use loop event as an opportinity to also check there's been
    // enough calls.
    CompLevel cur_level = comp_level(mh());
    CompLevel next_level = call_event(mh(), cur_level);
    CompLevel next_osr_level = loop_event(mh(), level);
    if (next_osr_level  == CompLevel_limited_profile) {
      next_osr_level = CompLevel_full_profile; // OSRs are supposed to be for very hot methods.
    }
    next_level = MAX2(next_level,
                      next_osr_level < CompLevel_full_optimization ? next_osr_level : cur_level);
    bool is_compiling = false;
    if (next_level != cur_level) {
      compile(mh, InvocationEntryBci, next_level, THREAD);
      is_compiling = true;
    }

    // Do the OSR version
    if (!is_compiling && next_osr_level != level) {
      compile(mh, bci, next_osr_level, THREAD);
    }
  }
}
Exemple #7
0
/*---------------------------------------------------------------------------*/
static
PT_THREAD(subscribe_pt(struct pt* pt, struct mqtt_connection* conn))
{
  PT_BEGIN(pt);

  DBG("MQTT - Sending subscribe message! topic %s topic_length %i\r\n",
      conn->out_packet.topic,
      conn->out_packet.topic_length);
  DBG("MQTT - Buffer space is %i \r\n",
      &conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr);

  /* Set up FHDR */
  conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_SUBSCRIBE | MQTT_FHDR_QOS_LEVEL_1;
  conn->out_packet.remaining_length = MQTT_MID_SIZE +
                                      MQTT_STRING_LEN_SIZE +
                                      conn->out_packet.topic_length +
                                      MQTT_QOS_SIZE;
  encode_remaining_length(conn->out_packet.remaining_length_enc,
                          &conn->out_packet.remaining_length_enc_bytes,
                          conn->out_packet.remaining_length);
  if(conn->out_packet.remaining_length_enc_bytes > 4) {
    call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL);
    printf("MQTT - Error, remaining length > 4 bytes\r\n");
    PT_EXIT(pt);
  }

  /* Write Fixed Header */
  PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr);
  PT_MQTT_WRITE_BYTES(conn,
                      conn->out_packet.remaining_length_enc,
                      conn->out_packet.remaining_length_enc_bytes);
  /* Write Variable Header */
  PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8));
  PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF));
  /* Write Payload */
  PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length >> 8));
  PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length & 0x00FF));
  PT_MQTT_WRITE_BYTES(conn,
                      conn->out_packet.topic,
                      conn->out_packet.topic_length);
  PT_MQTT_WRITE_BYTE(conn, conn->out_packet.qos);

  /* Send out buffer */
  send_out_buffer(conn);

  /* Wait for SUBACK. */
  reset_packet(&conn->in_packet);
  do {
    PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK);
  } while(conn->out_packet.qos_state != MQTT_QOS_STATE_GOT_ACK);
  reset_packet(&conn->in_packet);

  /* This is clear after the entire transaction is complete */
  conn->out_queue_full = 0;

  DBG("MQTT - Done in send_subscribe!\r\n");

  PT_END(pt);
}
Exemple #8
0
void AreaBullet::clear_overlaps(bool p_notify) {
	for (int i = overlappingObjects.size() - 1; 0 <= i; --i) {
		if (p_notify)
			call_event(overlappingObjects[i].object, PhysicsServer::AREA_BODY_REMOVED);
		overlappingObjects[i].object->on_exit_area(this);
	}
	overlappingObjects.clear();
}
Exemple #9
0
// Handle the invocation event.
void SimpleThresholdPolicy::method_invocation_event(const methodHandle& mh, const methodHandle& imh,
                                              CompLevel level, CompiledMethod* nm, JavaThread* thread) {
  if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh)) {
    CompLevel next_level = call_event(mh(), level, thread);
    if (next_level != level) {
      compile(mh, InvocationEntryBci, next_level, thread);
    }
  }
}
int 
lc_get_keystroke (void)
{
    int q;
    call_event ();
    q = x_key_value;
    x_key_value = 0;
    return q;
}
/*---------------------------------------------------------------------------*/
static void
handle_puback(struct mqtt_connection *conn)
{
  DBG("MQTT - Got PUBACK\n");

  conn->out_packet.qos_state = MQTT_QOS_STATE_GOT_ACK;
  conn->in_packet.mid = (conn->in_packet.payload[0] << 8) |
    (conn->in_packet.payload[1]);

  call_event(conn, MQTT_EVENT_PUBACK, &conn->in_packet.mid);
}
Exemple #12
0
void AreaBullet::remove_overlap(CollisionObjectBullet *p_object, bool p_notify) {
	for (int i = overlappingObjects.size() - 1; 0 <= i; --i) {
		if (overlappingObjects[i].object == p_object) {
			if (p_notify)
				call_event(overlappingObjects[i].object, PhysicsServer::AREA_BODY_REMOVED);
			overlappingObjects[i].object->on_exit_area(this);
			overlappingObjects.remove(i);
			break;
		}
	}
}
Exemple #13
0
// Handle the invocation event.
void AdvancedThresholdPolicy::method_invocation_event(methodHandle mh, methodHandle imh,
                                                      CompLevel level, TRAPS) {
  if (should_create_mdo(mh(), level)) {
    create_mdo(mh, THREAD);
  }
  if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh, InvocationEntryBci)) {
    CompLevel next_level = call_event(mh(), level);
    if (next_level != level) {
      compile(mh, InvocationEntryBci, next_level, THREAD);
    }
  }
}
Exemple #14
0
/**
 * Handles TCP events from Simple TCP
 */
static void
tcp_event(struct tcp_socket *s, void *ptr, tcp_socket_event_t event)
{
  struct mqtt_connection* conn = ptr;

  /* Take care of event */
  switch(event) {

    /* Fall through to manage different disconnect event the same way. */
    case TCP_SOCKET_CLOSED:
    case TCP_SOCKET_TIMEDOUT:
    case TCP_SOCKET_ABORTED: {

      ctimer_stop(&conn->keep_alive_timer);
      call_event(conn, MQTT_EVENT_DISCONNECTED, &event);

      /* If connecting retry */
      if(conn->state == MQTT_CONN_STATE_TCP_CONNECTING ||
         conn->auto_reconnect == 1) {
        DBG("MQTT - Disconnected by tcp event %d, reconnecting...",
            event);
        connect_tcp(conn);
      }
      else {
        conn->state = MQTT_CONN_STATE_NOT_CONNECTED;
      }
      break;
    }
    case TCP_SOCKET_CONNECTED: {
      DBG("MQTT - Got TCP_SOCKET_CONNECTED\r\n");
      conn->state = MQTT_CONN_STATE_TCP_CONNECTED;

      process_post(&mqtt_process, mqtt_do_connect_mqtt_event, conn);
      break;
    }
    case TCP_SOCKET_DATA_SENT: {
      DBG("MQTT - Got TCP_DATA_SENT\r\n");
      conn->out_buffer_sent = 1;
      conn->out_buffer_ptr = conn->out_buffer;

      ctimer_restart(&conn->keep_alive_timer);
      break;
    }

    default: {
      DBG("MQTT - TCP Event %d is currently not manged by the tcp event callback\r\n",
          event);
    }

  }

}
/*---------------------------------------------------------------------------*/
static void
handle_connack(struct mqtt_connection *conn)
{
  DBG("MQTT - Got CONNACK\n");

  if(conn->in_packet.payload[1] != 0) {
    PRINTF("MQTT - Connection refused with Return Code %i\n",
           conn->in_packet.payload[1]);
    call_event(conn,
               MQTT_EVENT_CONNECTION_REFUSED_ERROR,
               &conn->in_packet.payload[1]);
  }

  conn->out_packet.qos_state = MQTT_QOS_STATE_GOT_ACK;

  ctimer_set(&conn->keep_alive_timer, conn->keep_alive * CLOCK_SECOND,
             keep_alive_callback, conn);

  /* Always reset packet before callback since it might be used directly */
  conn->state = MQTT_CONN_STATE_CONNECTED_TO_BROKER;
  call_event(conn, MQTT_EVENT_CONNECTED, NULL);
}
/*---------------------------------------------------------------------------*/
static void
handle_unsuback(struct mqtt_connection *conn)
{
  DBG("MQTT - Got UNSUBACK\n");

  conn->out_packet.qos_state = MQTT_QOS_STATE_GOT_ACK;
  conn->in_packet.mid = (conn->in_packet.payload[0] << 8) |
    (conn->in_packet.payload[1]);

  if(conn->in_packet.mid != conn->out_packet.mid) {
    DBG("MQTT - Warning, got UNSUBACK with none matching MID. Currently there is"
        "no support for several concurrent UNSUBSCRIBE messages.\n");
  }

  call_event(conn, MQTT_EVENT_UNSUBACK, &conn->in_packet.mid);
}
Exemple #17
0
static void test_event_assignment_and_swap() {
    printf("\r\n********** Starting test_event_assignment_and_swap **********\r\n");
    ADerived aderived(10, 10);
    FunctionPointer1<void, const char*> fp_sa_tc1(sa_func_1);
    FunctionPointer1<void, int> fp_sa_tc2(sa_func_2);
    FunctionPointer0<void> fp_sa_noargs(sa_func_3);
    FunctionPointer1<void, MyArg> fp_sa_ntc(sa_ntc);
    FunctionPointer1<void, MyArg> fp_class_ntc(&aderived, &ADerived::print_virtual_arg);
    MyArg arg("test_event_assignment");
    Event e_sa_tc1(fp_sa_tc1.bind("test_event_assignment"));
    Event e_sa_tc2(fp_sa_tc2.bind(17));
    Event e_sa_noargs(fp_sa_noargs.bind());
    Event e_sa_ntc(fp_sa_ntc.bind(arg));
    Event e_class_ntc(fp_class_ntc.bind(arg));
    Event e1 = e_sa_tc1, e2 = e_class_ntc, e3;
    e3 = e_sa_noargs;

    // Swap them around like crazy. I'm going to regret this in the morning.
    swap_events_using_eq(e1, e_sa_noargs); // e1: fp_sa_noargs, e_sa_noargs: fp_sa_tcl
    swap_events_using_cc(e2, e_class_ntc); // Intentional NOOP, e2 = e_class_ntc: fp_class_ntc
    swap_events_using_eq(e_sa_ntc, e_sa_tc2); // e_sa_ntc: fp_sa_tc2, e_sa_tc2: fp_sa_ntc
    swap_events_using_cc(e3, e_sa_tc1); //e3: fp_sa_tc1, e_sa_tc1: fp_sa_noargs
    swap_events_using_eq(e_sa_noargs, e2); // e_sa_noargs: fp_class_ntc, e2: fp_sa_tc1
    swap_events_using_cc(e_sa_tc2, e_class_ntc); // e_sa_tc2: fp_class_ntc, e_class_ntc: fp_sa_ntc
    // Final assignments:
    //  e_sa_tc1: fp_sa_noargs
    //  e_sa_tc2: fp_class_ntc
    //  e_sa_noargs: fp_class_ntc
    //  e_sa_ntc: fp_sa_tc2
    //  e_class_ntc: fp_sa_ntc
    //  e1: fp_sa_noargs
    //  e2: fp_sa_tc1
    //  e3: fp_sa_tc1

    // Now call all of them and prepare for a headache
    call_event("e_sa_tc1", e_sa_tc1);
    call_event("e_sa_tc2", e_sa_tc2);
    call_event("e_sa_noargs", e_sa_noargs);
    call_event("e_sa_ntc", e_sa_ntc);
    call_event("e_class_ntc", e_class_ntc);
    call_event("e1", e1);
    call_event("e2", e2);
    call_event("e3", e3);
}
Exemple #18
0
/*---------------------------------------------------------------------------*/
static void
acked(struct tcp_socket *s)
{
  if(s->output_data_len > 0) {
    /* Copy the data in the outputbuf down and update outputbufptr and
       outputbuf_lastsent */

    if(s->output_data_send_nxt > 0) {
      memcpy(&s->output_data_ptr[0],
	     &s->output_data_ptr[s->output_data_send_nxt],
	     s->output_data_maxlen - s->output_data_send_nxt);
    }
    if(s->output_data_len < s->output_data_send_nxt) {
      printf("tcp: acked assertion failed s->output_data_len (%d) < s->output_data_send_nxt (%d)\n",
	     s->output_data_len,
	     s->output_data_send_nxt);
    }
    s->output_data_len -= s->output_data_send_nxt;
    s->output_data_send_nxt = 0;

    call_event(s, TCP_SOCKET_DATA_SENT);
  }
}
Exemple #19
0
// Handle the back branch event. Notice that we can compile the method
// with a regular entry from here.
void SimpleThresholdPolicy::method_back_branch_event(const methodHandle& mh, const methodHandle& imh,
                                                     int bci, CompLevel level, CompiledMethod* nm, JavaThread* thread) {
  // If the method is already compiling, quickly bail out.
  if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh)) {
    // Use loop event as an opportunity to also check there's been
    // enough calls.
    CompLevel cur_level = comp_level(mh());
    CompLevel next_level = call_event(mh(), cur_level, thread);
    CompLevel next_osr_level = loop_event(mh(), level, thread);

    next_level = MAX2(next_level,
                      next_osr_level < CompLevel_full_optimization ? next_osr_level : cur_level);
    bool is_compiling = false;
    if (next_level != cur_level) {
      compile(mh, InvocationEntryBci, next_level, thread);
      is_compiling = true;
    }

    // Do the OSR version
    if (!is_compiling && next_osr_level != level) {
      compile(mh, bci, next_osr_level, thread);
    }
  }
}
Exemple #20
0
/*---------------------------------------------------------------------------*/
static void
appcall(void *state)
{
  struct tcp_socket *s = state;

  if(uip_connected()) {
    /* Check if this connection originated in a local listen
       socket. We do this by checking the state pointer - if NULL,
       this is an incoming listen connection. If so, we need to
       connect the socket to the uip_conn and call the event
       function. */
    if(s == NULL) {
      for(s = list_head(socketlist);
	  s != NULL;
	  s = list_item_next(s)) {
	if(s->is_listening != 0 &&
	   s->listen_port != 0 &&
	   s->listen_port == uip_htons(uip_conn->lport)) {
	  s->is_listening = 0;
	  tcp_markconn(uip_conn, s);
	  call_event(s, TCP_SOCKET_CONNECTED);
	  break;
	}
      }
    } else {
      call_event(s, TCP_SOCKET_CONNECTED);
    }

    if(s == NULL) {
      uip_abort();
    } else {
      senddata(s);
    }
    return;
  }

  if(uip_timedout()) {
    call_event(s, TCP_SOCKET_TIMEDOUT);
    relisten(s);
  }

  if(uip_aborted()) {
    call_event(s, TCP_SOCKET_ABORTED);
    relisten(s);
  }

  if(s == NULL) {
    uip_abort();
    return;
  }
  
  if(uip_acked()) {
    acked(s);
  }
  if(uip_newdata()) {
    newdata(s);
  }

  if(uip_rexmit() ||
     uip_newdata() ||
     uip_acked()) {
    senddata(s);
  } else if(uip_poll()) {
    senddata(s);
  }

  if(uip_closed()) {
    tcp_markconn(uip_conn, NULL);
    call_event(s, TCP_SOCKET_CLOSED);
    relisten(s);
  }
}
/*---------------------------------------------------------------------------*/
static int
tcp_input(struct tcp_socket *s,
          void *ptr,
          const uint8_t *input_data_ptr,
          int input_data_len)
{
  struct mqtt_connection *conn = ptr;
  uint32_t pos = 0;
  uint32_t copy_bytes = 0;
  uint8_t byte;

  if(input_data_len == 0) {
    return 0;
  }

  if(conn->in_packet.packet_received) {
    reset_packet(&conn->in_packet);
  }

  DBG("tcp_input with %i bytes of data:\n", input_data_len);

  /* Read the fixed header field, if we do not have it */
  if(!conn->in_packet.fhdr) {
    conn->in_packet.fhdr = input_data_ptr[pos++];
    conn->in_packet.byte_counter++;

    DBG("MQTT - Read VHDR '%02X'\n", conn->in_packet.fhdr);

    if(pos >= input_data_len) {
      return 0;
    }
  }

  /* Read the Remaining Length field, if we do not have it */
  if(!conn->in_packet.has_remaining_length) {
    do {
      if(pos >= input_data_len) {
        return 0;
      }

      byte = input_data_ptr[pos++];
      conn->in_packet.byte_counter++;
      conn->in_packet.remaining_length_bytes++;
      DBG("MQTT - Read Remaining Length byte\n");

      if(conn->in_packet.byte_counter > 5) {
        call_event(conn, MQTT_EVENT_ERROR, NULL);
        DBG("Received more then 4 byte 'remaining lenght'.");
        return 0;
      }

      conn->in_packet.remaining_length +=
        (byte & 127) * conn->in_packet.remaining_multiplier;
      conn->in_packet.remaining_multiplier *= 128;
    } while((byte & 128) != 0);

    DBG("MQTT - Finished reading remaining length byte\n");
    conn->in_packet.has_remaining_length = 1;
  }

  /*
   * Check for unsupported payload length. Will read all incoming data from the
   * server in any case and then reset the packet.
   *
   * TODO: Decide if we, for example, want to disconnect instead.
   */
  if((conn->in_packet.remaining_length > MQTT_INPUT_BUFF_SIZE) &&
     (conn->in_packet.fhdr & 0xF0) != MQTT_FHDR_MSG_TYPE_PUBLISH) {

    PRINTF("MQTT - Error, unsupported payload size for non-PUBLISH message\n");

    conn->in_packet.byte_counter += input_data_len;
    if(conn->in_packet.byte_counter >=
       (MQTT_FHDR_SIZE + conn->in_packet.remaining_length)) {
      conn->in_packet.packet_received = 1;
    }
    return 0;
  }

  /*
   * Supported payload, reads out both VHDR and Payload of all packets.
   *
   * Note: There will always be at least one byte left to read when we enter
   *       this loop.
   */
  while(conn->in_packet.byte_counter <
        (MQTT_FHDR_SIZE + conn->in_packet.remaining_length)) {

    if((conn->in_packet.fhdr & 0xF0) == MQTT_FHDR_MSG_TYPE_PUBLISH &&
       conn->in_packet.topic_received == 0) {
      parse_publish_vhdr(conn, &pos, input_data_ptr, input_data_len);
    }

    /* Read in as much as we can into the packet payload */
    copy_bytes = MIN(input_data_len - pos,
                     MQTT_INPUT_BUFF_SIZE - conn->in_packet.payload_pos);
    DBG("- Copied %lu payload bytes\n", copy_bytes);
    memcpy(&conn->in_packet.payload[conn->in_packet.payload_pos],
           &input_data_ptr[pos],
           copy_bytes);
    conn->in_packet.byte_counter += copy_bytes;
    conn->in_packet.payload_pos += copy_bytes;
    pos += copy_bytes;

    uint8_t i;
    DBG("MQTT - Copied bytes: \n");
    for(i = 0; i < copy_bytes; i++) {
      DBG("%02X ", conn->in_packet.payload[i]);
    }
    DBG("\n");

    /* Full buffer, shall only happen to PUBLISH messages. */
    if(MQTT_INPUT_BUFF_SIZE - conn->in_packet.payload_pos == 0) {
      conn->in_publish_msg.payload_chunk = conn->in_packet.payload;
      conn->in_publish_msg.payload_chunk_length = MQTT_INPUT_BUFF_SIZE;
      conn->in_publish_msg.payload_left -= MQTT_INPUT_BUFF_SIZE;

      handle_publish(conn);

      conn->in_publish_msg.payload_chunk = conn->in_packet.payload;
      conn->in_packet.payload_pos = 0;
    }

    if(pos >= input_data_len &&
       (conn->in_packet.byte_counter < (MQTT_FHDR_SIZE + conn->in_packet.remaining_length))) {
      return 0;
    }
  }

  /* Debug information */
  DBG("\n");
  /* Take care of input */
  DBG("MQTT - Finished reading packet!\n");
  /* What to return? */
  DBG("MQTT - total data was %i bytes of data. \n",
      (MQTT_FHDR_SIZE + conn->in_packet.remaining_length));

  /* Handle packet here. */
  switch(conn->in_packet.fhdr & 0xF0) {
  case MQTT_FHDR_MSG_TYPE_CONNACK:
    handle_connack(conn);
    break;
  case MQTT_FHDR_MSG_TYPE_PUBLISH:
    /* This is the only or the last chunk of publish payload */
    conn->in_publish_msg.payload_chunk = conn->in_packet.payload;
    conn->in_publish_msg.payload_chunk_length = conn->in_packet.payload_pos;
    conn->in_publish_msg.payload_left = 0;
    handle_publish(conn);
    break;
  case MQTT_FHDR_MSG_TYPE_PUBACK:
    handle_puback(conn);
    break;
  case MQTT_FHDR_MSG_TYPE_SUBACK:
    handle_suback(conn);
    break;
  case MQTT_FHDR_MSG_TYPE_UNSUBACK:
    handle_unsuback(conn);
    break;
  case MQTT_FHDR_MSG_TYPE_PINGRESP:
    handle_pingresp(conn);
    break;

  /* QoS 2 not implemented yet */
  case MQTT_FHDR_MSG_TYPE_PUBREC:
  case MQTT_FHDR_MSG_TYPE_PUBREL:
  case MQTT_FHDR_MSG_TYPE_PUBCOMP:
    call_event(conn, MQTT_EVENT_NOT_IMPLEMENTED_ERROR, NULL);
    PRINTF("MQTT - Got unhandled MQTT Message Type '%i'",
           (conn->in_packet.fhdr & 0xF0));
    break;

  default:
    /* All server-only message */
    PRINTF("MQTT - Got MQTT Message Type '%i'", (conn->in_packet.fhdr & 0xF0));
    break;
  }

  conn->in_packet.packet_received = 1;

  return 0;
}
Exemple #22
0
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(mqtt_process, ev, data)
{
  static struct mqtt_connection* conn;
  static uip_ipaddr_t* ipaddr = NULL;

  PROCESS_BEGIN();
  while(1) {
    PROCESS_WAIT_EVENT();

    if(ev == mqtt_do_connect_tcp_event) {
      conn = data;
      DBG("MQTT - Got mqtt_do_connect_tcp_event!\r\n");
      connect_tcp(conn);
    }
    if(ev == mqtt_do_connect_mqtt_event) {
      conn = data;
      DBG("MQTT - Got mqtt_do_connect_mqtt_event!\r\n");

      PT_INIT(&conn->out_proto_thread);
      while(connect_pt(&conn->out_proto_thread, conn) != PT_ENDED) {
        PT_MQTT_WAIT_SEND();
      }
    }
    if(ev == mqtt_do_disconnect_mqtt_event) {
      conn = data;
      DBG("MQTT - Got mqtt_do_disconnect_mqtt_event!\r\n");

      PT_INIT(&conn->out_proto_thread);
      while(disconnect_pt(&conn->out_proto_thread, conn) != PT_ENDED) {
        PT_MQTT_WAIT_SEND();
      }
    }
    if(ev == mqtt_do_pingreq_event) {
      conn = data;
      DBG("MQTT - Got mqtt_do_pingreq_event!\r\n");

      PT_INIT(&conn->out_proto_thread);
      while(pingreq_pt(&conn->out_proto_thread, conn) != PT_ENDED) {
        PT_MQTT_WAIT_SEND();
      }
    }
    if(ev == mqtt_do_subscribe_event) {
      conn = data;
      DBG("MQTT - Got mqtt_do_subscribe_mqtt_event!\r\n");

      PT_INIT(&conn->out_proto_thread);
      while(subscribe_pt(&conn->out_proto_thread, conn) != PT_ENDED) {
        PT_MQTT_WAIT_SEND();
      }
    }
    if(ev == mqtt_do_unsubscribe_event) {
        conn = data;
        DBG("MQTT - Got mqtt_do_unsubscribe_mqtt_event!\r\n");

        PT_INIT(&conn->out_proto_thread);
        while(unsubscribe_pt(&conn->out_proto_thread, conn) != PT_ENDED) {
          PT_MQTT_WAIT_SEND();
        }
      }
    if(ev == mqtt_do_publish_event) {
      conn = data;
      DBG("MQTT - Got mqtt_do_publish_mqtt_event!\r\n");

      PT_INIT(&conn->out_proto_thread);
      while(publish_pt(&conn->out_proto_thread, conn) != PT_ENDED) {
        PT_MQTT_WAIT_SEND();
      }
    }

#if 0
    if(ev == mqtt_do_publish_event) {

    }
#endif
    /* mDNS event - either found a hostname, or not. */
    if(ev == mdns_event_found) {
      if((char *)data != NULL && mdns_lookup((char *)data) != NULL) {
        ipaddr = mdns_lookup((char *)data);

        DBG("MQTT - Host found with ip %i %i %i %i TCP connecting...\r\n",
               ipaddr->u8[12],
               ipaddr->u8[13],
               ipaddr->u8[14],
               ipaddr->u8[15]);
      } else {
        printf("MQTT - Host not found, cannot continue.\r\n");
      }

      /* Find the connection(s) that are waiting for this lookup. Note that it
       * could possibly be more then one connection. */
      for(conn = list_head(mqtt_conn_list);
          conn != NULL;
          conn = list_item_next(conn)) {
        if( conn->state == MQTT_CONN_STATE_DNS_LOOKUP &&
            strcmp( (char*)data, conn->server_host ) == 0 ) {

          /* Update the connection of the DNS error or connect, depending on the
           * DNS lookup result.
           */
          if( ipaddr == NULL ) {
            conn->state = MQTT_CONN_STATE_DNS_ERROR;
            call_event(conn, MQTT_EVENT_DNS_ERROR, NULL);
          } else {
            uip_ipaddr_copy( &(conn->server_ip), ipaddr );
            process_post(&mqtt_process, mqtt_do_connect_tcp_event, conn);
          }
        }
      }
    }
  }
  PROCESS_END();
}
Exemple #23
0
/*---------------------------------------------------------------------------*/
static void
appcall(void *state)
{
  struct tcp_socket *s = state;

  if(s != NULL && s->c != NULL && s->c != uip_conn) {
    /* Safe-guard: this should not happen, as the incoming event relates to
     * a previous connection */
    return;
  }
  if(uip_connected()) {
    /* Check if this connection originated in a local listen
       socket. We do this by checking the state pointer - if NULL,
       this is an incoming listen connection. If so, we need to
       connect the socket to the uip_conn and call the event
       function. */
    if(s == NULL) {
      for(s = list_head(socketlist);
	  s != NULL;
	  s = list_item_next(s)) {
	if((s->flags & TCP_SOCKET_FLAGS_LISTENING) != 0 &&
	   s->listen_port != 0 &&
	   s->listen_port == uip_htons(uip_conn->lport)) {
	  s->flags &= ~TCP_SOCKET_FLAGS_LISTENING;
          s->output_data_max_seg = uip_mss();
	  tcp_markconn(uip_conn, s);
	  call_event(s, TCP_SOCKET_CONNECTED);
	  break;
	}
      }
    } else {
      s->output_data_max_seg = uip_mss();
      call_event(s, TCP_SOCKET_CONNECTED);
    }

    if(s == NULL) {
      uip_abort();
    } else {
      if(uip_newdata()) {
        newdata(s);
      }
      senddata(s);
    }
    return;
  }

  if(uip_timedout()) {
    call_event(s, TCP_SOCKET_TIMEDOUT);
    relisten(s);
  }

  if(uip_aborted()) {
    tcp_markconn(uip_conn, NULL);
    call_event(s, TCP_SOCKET_ABORTED);
    relisten(s);

  }

  if(s == NULL) {
    uip_abort();
    return;
  }

  if(uip_acked()) {
    acked(s);
  }
  if(uip_newdata()) {
    newdata(s);
  }

  if(uip_rexmit() ||
     uip_newdata() ||
     uip_acked()) {
    senddata(s);
  } else if(uip_poll()) {
    senddata(s);
  }

  if(s->output_data_len == 0 && s->flags & TCP_SOCKET_FLAGS_CLOSING) {
    s->flags &= ~TCP_SOCKET_FLAGS_CLOSING;
    uip_close();
    s->c = NULL;
    tcp_markconn(uip_conn, NULL);
    s->c = NULL;
    /*call_event(s, TCP_SOCKET_CLOSED);*/
    relisten(s);
  }

  if(uip_closed()) {
    tcp_markconn(uip_conn, NULL);
    s->c = NULL;
    call_event(s, TCP_SOCKET_CLOSED);
    relisten(s);
  }
}
Exemple #24
0
/*---------------------------------------------------------------------------*/
static
PT_THREAD(connect_pt(struct pt* pt, struct mqtt_connection* conn))
{
  PT_BEGIN(pt);

  DBG("MQTT - Sending CONNECT message...\r\n");

  /* Set up FHDR */
  conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_CONNECT;
  conn->out_packet.remaining_length = 0;
  conn->out_packet.remaining_length += MQTT_connect_vhdr_flags_SIZE;
  conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->client_id);
  conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->credentials.username);
  conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->credentials.password);
  conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->will.topic);
  conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->will.message);
  encode_remaining_length(conn->out_packet.remaining_length_enc,
                          &conn->out_packet.remaining_length_enc_bytes,
                          conn->out_packet.remaining_length);
  if(conn->out_packet.remaining_length_enc_bytes > 4) {
    call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL);
    printf("MQTT - Error, remaining length > 4 bytes\r\n");
    PT_EXIT(pt);
  }

  /* Write Fixed Header */
  PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr);
  PT_MQTT_WRITE_BYTES(conn,
                      conn->out_packet.remaining_length_enc,
                      conn->out_packet.remaining_length_enc_bytes);
  PT_MQTT_WRITE_BYTE(conn, 0);
  PT_MQTT_WRITE_BYTE(conn, 6);
  PT_MQTT_WRITE_BYTES(conn, (uint8_t*)MQTT_PROTOCOL_NAME, 6);
  PT_MQTT_WRITE_BYTE(conn, MQTT_PROTOCOL_VERSION);
  PT_MQTT_WRITE_BYTE(conn, conn->connect_vhdr_flags);
  PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive >> 8));
  PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive & 0x00FF));
  PT_MQTT_WRITE_BYTE(conn, conn->client_id.length << 8);
  PT_MQTT_WRITE_BYTE(conn, conn->client_id.length & 0x00FF);
  PT_MQTT_WRITE_BYTES(conn, conn->client_id.string, conn->client_id.length);
  if(conn->connect_vhdr_flags & MQTT_VHDR_WILL_FLAG) {
    PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length << 8);
    PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length & 0x00FF);
    PT_MQTT_WRITE_BYTES(conn, conn->will.topic.string, conn->will.topic.length);
    PT_MQTT_WRITE_BYTE(conn, conn->will.message.length << 8);
    PT_MQTT_WRITE_BYTE(conn, conn->will.message.length & 0x00FF);
    PT_MQTT_WRITE_BYTES(conn, conn->will.message.string, conn->will.message.length);
    DBG("MQTT - Setting will topic to '%s' %i bytes and message to '%s' %i bytes\r\n",
        conn->will.topic.string,
        conn->will.topic.length,
        conn->will.message.string,
        conn->will.message.length);
  }
  if(conn->connect_vhdr_flags & MQTT_VHDR_USERNAME_FLAG) {
    DBG("MQTT - Setting username\r\n");
    PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length << 8);
    PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length & 0x00FF);
    PT_MQTT_WRITE_BYTES(conn,
                        conn->credentials.username.string,
                        conn->credentials.username.length);
  }
  if(conn->connect_vhdr_flags & MQTT_VHDR_PASSWORD_FLAG) {
    DBG("MQTT - Setting password\r\n");    
    PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length << 8);
    PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length & 0x00FF);
    PT_MQTT_WRITE_BYTES(conn,
                        conn->credentials.password.string,
                        conn->credentials.password.length);
  }

  /* Send out buffer */
  send_out_buffer(conn);
  conn->state = MQTT_CONN_STATE_CONNECTING_TO_BROKER;

  /* Wait for CONNACK */
  reset_packet(&conn->in_packet);
  do {
    PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK);
  } while(conn->out_packet.qos_state != MQTT_QOS_STATE_GOT_ACK);
  reset_packet(&conn->in_packet);

  DBG("MQTT - Done sending CONNECT since we got CONNACK!\r\n");

#if DEBUG_MQTT == 1
  DBG("MQTT - Sending CONNECT message: \r\n");
  uint16_t i;
  for( i = 0; i < (conn->out_buffer_ptr - conn->out_buffer); i++ ) {
    DBG( "%02X ", conn->out_buffer[i] );
  }
  DBG("\r\n");
#endif

  PT_END(pt);
}
// Handle the back branch event. Notice that we can compile the method
// with a regular entry from here.
void AdvancedThresholdPolicy::method_back_branch_event(const methodHandle& mh, const methodHandle& imh,
                                                       int bci, CompLevel level, nmethod* nm, JavaThread* thread) {
  if (should_create_mdo(mh(), level)) {
    create_mdo(mh, thread);
  }
  // Check if MDO should be created for the inlined method
  if (should_create_mdo(imh(), level)) {
    create_mdo(imh, thread);
  }

  if (is_compilation_enabled()) {
    CompLevel next_osr_level = loop_event(imh(), level);
    CompLevel max_osr_level = (CompLevel)imh->highest_osr_comp_level();
    // At the very least compile the OSR version
    if (!CompileBroker::compilation_is_in_queue(imh) && (next_osr_level != level)) {
      compile(imh, bci, next_osr_level, thread);
    }

    // Use loop event as an opportunity to also check if there's been
    // enough calls.
    CompLevel cur_level, next_level;
    if (mh() != imh()) { // If there is an enclosing method
      guarantee(nm != NULL, "Should have nmethod here");
      cur_level = comp_level(mh());
      next_level = call_event(mh(), cur_level);

      if (max_osr_level == CompLevel_full_optimization) {
        // The inlinee OSRed to full opt, we need to modify the enclosing method to avoid deopts
        bool make_not_entrant = false;
        if (nm->is_osr_method()) {
          // This is an osr method, just make it not entrant and recompile later if needed
          make_not_entrant = true;
        } else {
          if (next_level != CompLevel_full_optimization) {
            // next_level is not full opt, so we need to recompile the
            // enclosing method without the inlinee
            cur_level = CompLevel_none;
            make_not_entrant = true;
          }
        }
        if (make_not_entrant) {
          if (PrintTieredEvents) {
            int osr_bci = nm->is_osr_method() ? nm->osr_entry_bci() : InvocationEntryBci;
            print_event(MAKE_NOT_ENTRANT, mh(), mh(), osr_bci, level);
          }
          nm->make_not_entrant();
        }
      }
      if (!CompileBroker::compilation_is_in_queue(mh)) {
        // Fix up next_level if necessary to avoid deopts
        if (next_level == CompLevel_limited_profile && max_osr_level == CompLevel_full_profile) {
          next_level = CompLevel_full_profile;
        }
        if (cur_level != next_level) {
          compile(mh, InvocationEntryBci, next_level, thread);
        }
      }
    } else {
      cur_level = comp_level(imh());
      next_level = call_event(imh(), cur_level);
      if (!CompileBroker::compilation_is_in_queue(imh) && (next_level != cur_level)) {
        compile(imh, InvocationEntryBci, next_level, thread);
      }
    }
  }
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(publish_pt(struct pt *pt, struct mqtt_connection *conn))
{
  PT_BEGIN(pt);

  DBG("MQTT - Sending publish message! topic %s topic_length %i\n",
      conn->out_packet.topic,
      conn->out_packet.topic_length);
  DBG("MQTT - Buffer space is %i \n",
      &conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr);

  /* Set up FHDR */
  conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_PUBLISH |
    conn->out_packet.qos << 1;
  if(conn->out_packet.retain == MQTT_RETAIN_ON) {
    conn->out_packet.fhdr |= MQTT_FHDR_RETAIN_FLAG;
  }
  conn->out_packet.remaining_length = MQTT_STRING_LEN_SIZE +
    conn->out_packet.topic_length +
    conn->out_packet.payload_size;
  if(conn->out_packet.qos > MQTT_QOS_LEVEL_0) {
    conn->out_packet.remaining_length += MQTT_MID_SIZE;
  }
  encode_remaining_length(conn->out_packet.remaining_length_enc,
                          &conn->out_packet.remaining_length_enc_bytes,
                          conn->out_packet.remaining_length);
  if(conn->out_packet.remaining_length_enc_bytes > 4) {
    call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL);
    PRINTF("MQTT - Error, remaining length > 4 bytes\n");
    PT_EXIT(pt);
  }

  /* Write Fixed Header */
  PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr);
  PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.remaining_length_enc,
                      conn->out_packet.remaining_length_enc_bytes);
  /* Write Variable Header */
  PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length >> 8));
  PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length & 0x00FF));
  PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.topic,
                      conn->out_packet.topic_length);
  if(conn->out_packet.qos > MQTT_QOS_LEVEL_0) {
    PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8));
    PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF));
  }
  /* Write Payload */
  PT_MQTT_WRITE_BYTES(conn,
                      conn->out_packet.payload,
                      conn->out_packet.payload_size);

  send_out_buffer(conn);
  timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT);

  /*
   * If QoS is zero then wait until the message has been sent, since there is
   * no ACK to wait for.
   *
   * Also notify the app will not be notified via PUBACK or PUBCOMP
   */
  if(conn->out_packet.qos == 0) {
    process_post(conn->app_process, mqtt_update_event, NULL);
  } else if(conn->out_packet.qos == 1) {
    /* Wait for PUBACK */
    reset_packet(&conn->in_packet);
    PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK ||
                  timer_expired(&conn->t));
    if(timer_expired(&conn->t)) {
      DBG("Timeout waiting for PUBACK\n");
    }
    if(conn->in_packet.mid != conn->out_packet.mid) {
      DBG("MQTT - Warning, got PUBACK with none matching MID. Currently there "
          "is no support for several concurrent PUBLISH messages.\n");
    }
  } else if(conn->out_packet.qos == 2) {
    DBG("MQTT - QoS not implemented yet.\n");
    /* Should wait for PUBREC, send PUBREL and then wait for PUBCOMP */
  }

  reset_packet(&conn->in_packet);

  /* This is clear after the entire transaction is complete */
  conn->out_queue_full = 0;

  DBG("MQTT - Publish Enqueued\n");

  PT_END(pt);
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(unsubscribe_pt(struct pt *pt, struct mqtt_connection *conn))
{
  PT_BEGIN(pt);

  DBG("MQTT - Sending unsubscribe message on topic %s topic_length %i\n",
      conn->out_packet.topic,
      conn->out_packet.topic_length);
  DBG("MQTT - Buffer space is %i \n",
      &conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr);

  /* Set up FHDR */
  conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_UNSUBSCRIBE |
    MQTT_FHDR_QOS_LEVEL_1;
  conn->out_packet.remaining_length = MQTT_MID_SIZE +
    MQTT_STRING_LEN_SIZE +
    conn->out_packet.topic_length;
  encode_remaining_length(conn->out_packet.remaining_length_enc,
                          &conn->out_packet.remaining_length_enc_bytes,
                          conn->out_packet.remaining_length);
  if(conn->out_packet.remaining_length_enc_bytes > 4) {
    call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL);
    PRINTF("MQTT - Error, remaining length > 4 bytes\n");
    PT_EXIT(pt);
  }

  /* Write Fixed Header */
  PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr);
  PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.remaining_length_enc,
                      conn->out_packet.remaining_length_enc_bytes);
  /* Write Variable Header */
  PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8));
  PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF));
  /* Write Payload */
  PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length >> 8));
  PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length & 0x00FF));
  PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.topic,
                      conn->out_packet.topic_length);

  /* Send out buffer */
  send_out_buffer(conn);
  timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT);

  /* Wait for UNSUBACK */
  reset_packet(&conn->in_packet);
  PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK ||
                timer_expired(&conn->t));

  if(timer_expired(&conn->t)) {
    DBG("Timeout waiting for UNSUBACK\n");
  }

  reset_packet(&conn->in_packet);

  /* This is clear after the entire transaction is complete */
  conn->out_queue_full = 0;

  DBG("MQTT - Done writing subscribe message to out buffer!\n");

  PT_END(pt);
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(connect_pt(struct pt *pt, struct mqtt_connection *conn))
{
  PT_BEGIN(pt);

  DBG("MQTT - Sending CONNECT message...\n");

  /* Set up FHDR */
  conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_CONNECT;
  conn->out_packet.remaining_length = 0;
  conn->out_packet.remaining_length += MQTT_CONNECT_VHDR_FLAGS_SIZE;
  conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->client_id);
  conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->credentials.username);
  conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->credentials.password);
  conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->will.topic);
  conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->will.message);
  encode_remaining_length(conn->out_packet.remaining_length_enc,
                          &conn->out_packet.remaining_length_enc_bytes,
                          conn->out_packet.remaining_length);
  if(conn->out_packet.remaining_length_enc_bytes > 4) {
    call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL);
    PRINTF("MQTT - Error, remaining length > 4 bytes\n");
    PT_EXIT(pt);
  }

  /* Write Fixed Header */
  PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr);
  PT_MQTT_WRITE_BYTES(conn,
                      conn->out_packet.remaining_length_enc,
                      conn->out_packet.remaining_length_enc_bytes);
  PT_MQTT_WRITE_BYTE(conn, 0);
  PT_MQTT_WRITE_BYTE(conn, 6);
  PT_MQTT_WRITE_BYTES(conn, (uint8_t *)MQTT_PROTOCOL_NAME, 6);
  PT_MQTT_WRITE_BYTE(conn, MQTT_PROTOCOL_VERSION);
  PT_MQTT_WRITE_BYTE(conn, conn->connect_vhdr_flags);
  PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive >> 8));
  PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive & 0x00FF));
  PT_MQTT_WRITE_BYTE(conn, conn->client_id.length << 8);
  PT_MQTT_WRITE_BYTE(conn, conn->client_id.length & 0x00FF);
  PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->client_id.string,
                      conn->client_id.length);
  if(conn->connect_vhdr_flags & MQTT_VHDR_WILL_FLAG) {
    PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length << 8);
    PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length & 0x00FF);
    PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->will.topic.string,
                        conn->will.topic.length);
    PT_MQTT_WRITE_BYTE(conn, conn->will.message.length << 8);
    PT_MQTT_WRITE_BYTE(conn, conn->will.message.length & 0x00FF);
    PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->will.message.string,
                        conn->will.message.length);
    DBG("MQTT - Setting will topic to '%s' %u bytes and message to '%s' %u bytes\n",
        conn->will.topic.string,
        conn->will.topic.length,
        conn->will.message.string,
        conn->will.message.length);
  }
  if(conn->connect_vhdr_flags & MQTT_VHDR_USERNAME_FLAG) {
    PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length << 8);
    PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length & 0x00FF);
    PT_MQTT_WRITE_BYTES(conn,
                        (uint8_t *)conn->credentials.username.string,
                        conn->credentials.username.length);
  }
  if(conn->connect_vhdr_flags & MQTT_VHDR_PASSWORD_FLAG) {
    PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length << 8);
    PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length & 0x00FF);
    PT_MQTT_WRITE_BYTES(conn,
                        (uint8_t *)conn->credentials.password.string,
                        conn->credentials.password.length);
  }

  /* Send out buffer */
  send_out_buffer(conn);
  conn->state = MQTT_CONN_STATE_CONNECTING_TO_BROKER;

  timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT);

  /* Wait for CONNACK */
  reset_packet(&conn->in_packet);
  PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK ||
                timer_expired(&conn->t));
  if(timer_expired(&conn->t)) {
    DBG("Timeout waiting for CONNACK\n");
    /* We stick to the letter of the spec here: Tear the connection down */
    mqtt_disconnect(conn);
  }
  reset_packet(&conn->in_packet);

  DBG("MQTT - Done sending CONNECT\n");

#if DEBUG_MQTT == 1
  DBG("MQTT - CONNECT message sent: \n");
  uint16_t i;
  for(i = 0; i < (conn->out_buffer_ptr - conn->out_buffer); i++) {
    DBG("%02X ", conn->out_buffer[i]);
  }
  DBG("\n");
#endif

  PT_END(pt);
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(mqtt_process, ev, data)
{
  static struct mqtt_connection *conn;

  PROCESS_BEGIN();

  while(1) {
    PROCESS_WAIT_EVENT();

    if(ev == mqtt_abort_now_event) {
      DBG("MQTT - Abort\n");
      conn = data;
      conn->state = MQTT_CONN_STATE_ABORT_IMMEDIATE;

      abort_connection(conn);
    }
    if(ev == mqtt_do_connect_tcp_event) {
      conn = data;
      DBG("MQTT - Got mqtt_do_connect_tcp_event!\n");
      connect_tcp(conn);
    }
    if(ev == mqtt_do_connect_mqtt_event) {
      conn = data;
      conn->socket.output_data_max_seg = conn->max_segment_size;
      DBG("MQTT - Got mqtt_do_connect_mqtt_event!\n");

      if(conn->out_buffer_sent == 1) {
        PT_INIT(&conn->out_proto_thread);
        while(connect_pt(&conn->out_proto_thread, conn) < PT_EXITED &&
              conn->state != MQTT_CONN_STATE_ABORT_IMMEDIATE) {
          PT_MQTT_WAIT_SEND();
        }
      }
    }
    if(ev == mqtt_do_disconnect_mqtt_event) {
      conn = data;
      DBG("MQTT - Got mqtt_do_disconnect_mqtt_event!\n");

      /* Send MQTT Disconnect if we are connected */
      if(conn->state == MQTT_CONN_STATE_SENDING_MQTT_DISCONNECT) {
        if(conn->out_buffer_sent == 1) {
          PT_INIT(&conn->out_proto_thread);
          while(disconnect_pt(&conn->out_proto_thread, conn) < PT_EXITED &&
                conn->state != MQTT_CONN_STATE_ABORT_IMMEDIATE) {
            PT_MQTT_WAIT_SEND();
          }
          abort_connection(conn);
          call_event(conn, MQTT_EVENT_DISCONNECTED, &ev);
        } else {
          process_post(&mqtt_process, mqtt_do_disconnect_mqtt_event, conn);
        }
      }
    }
    if(ev == mqtt_do_pingreq_event) {
      conn = data;
      DBG("MQTT - Got mqtt_do_pingreq_event!\n");

      if(conn->out_buffer_sent == 1 &&
         conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) {
        PT_INIT(&conn->out_proto_thread);
        while(pingreq_pt(&conn->out_proto_thread, conn) < PT_EXITED &&
              conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) {
          PT_MQTT_WAIT_SEND();
        }
      }
    }
    if(ev == mqtt_do_subscribe_event) {
      conn = data;
      DBG("MQTT - Got mqtt_do_subscribe_mqtt_event!\n");

      if(conn->out_buffer_sent == 1 &&
         conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) {
        PT_INIT(&conn->out_proto_thread);
        while(subscribe_pt(&conn->out_proto_thread, conn) < PT_EXITED &&
              conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) {
          PT_MQTT_WAIT_SEND();
        }
      }
    }
    if(ev == mqtt_do_unsubscribe_event) {
      conn = data;
      DBG("MQTT - Got mqtt_do_unsubscribe_mqtt_event!\n");

      if(conn->out_buffer_sent == 1 &&
         conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) {
        PT_INIT(&conn->out_proto_thread);
        while(unsubscribe_pt(&conn->out_proto_thread, conn) < PT_EXITED &&
              conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) {
          PT_MQTT_WAIT_SEND();
        }
      }
    }
    if(ev == mqtt_do_publish_event) {
      conn = data;
      DBG("MQTT - Got mqtt_do_publish_mqtt_event!\n");

      if(conn->out_buffer_sent == 1 &&
         conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) {
        PT_INIT(&conn->out_proto_thread);
        while(publish_pt(&conn->out_proto_thread, conn) < PT_EXITED &&
              conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) {
          PT_MQTT_WAIT_SEND();
        }
      }
    }
  }
  PROCESS_END();
}