1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation
2425bb815Sopenharmony_ci *
3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License.
5425bb815Sopenharmony_ci * You may obtain a copy of the License at
6425bb815Sopenharmony_ci *
7425bb815Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8425bb815Sopenharmony_ci *
9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS
11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and
13425bb815Sopenharmony_ci * limitations under the License.
14425bb815Sopenharmony_ci */
15425bb815Sopenharmony_ci
16425bb815Sopenharmony_ci#include "debugger.h"
17425bb815Sopenharmony_ci#include "jcontext.h"
18425bb815Sopenharmony_ci#include "jerryscript.h"
19425bb815Sopenharmony_ci
20425bb815Sopenharmony_ci#if ENABLED (JERRY_DEBUGGER)
21425bb815Sopenharmony_ci
22425bb815Sopenharmony_ci/**
23425bb815Sopenharmony_ci * Minimum number of bytes transmitted or received.
24425bb815Sopenharmony_ci */
25425bb815Sopenharmony_ci#define JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE 64
26425bb815Sopenharmony_ci
27425bb815Sopenharmony_ci/**
28425bb815Sopenharmony_ci * Sleep time in milliseconds between each jerry_debugger_receive call
29425bb815Sopenharmony_ci */
30425bb815Sopenharmony_ci#define JERRY_DEBUGGER_TRANSPORT_TIMEOUT 10
31425bb815Sopenharmony_ci
32425bb815Sopenharmony_ci/**
33425bb815Sopenharmony_ci * Add a new transport layer.
34425bb815Sopenharmony_ci */
35425bb815Sopenharmony_civoid
36425bb815Sopenharmony_cijerry_debugger_transport_add (jerry_debugger_transport_header_t *header_p, /**< transport implementation */
37425bb815Sopenharmony_ci                              size_t send_message_header_size, /**< header bytes reserved for outgoing messages */
38425bb815Sopenharmony_ci                              size_t max_send_message_size, /**< maximum number of bytes transmitted in a message */
39425bb815Sopenharmony_ci                              size_t receive_message_header_size, /**< header bytes reserved for incoming messages */
40425bb815Sopenharmony_ci                              size_t max_receive_message_size) /**< maximum number of bytes received in a message */
41425bb815Sopenharmony_ci{
42425bb815Sopenharmony_ci  JERRY_ASSERT (max_send_message_size > JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE
43425bb815Sopenharmony_ci                && max_receive_message_size > JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE);
44425bb815Sopenharmony_ci
45425bb815Sopenharmony_ci  header_p->next_p = JERRY_CONTEXT (debugger_transport_header_p);
46425bb815Sopenharmony_ci  JERRY_CONTEXT (debugger_transport_header_p) = header_p;
47425bb815Sopenharmony_ci
48425bb815Sopenharmony_ci  uint8_t *payload_p;
49425bb815Sopenharmony_ci  size_t max_send_size;
50425bb815Sopenharmony_ci  size_t max_receive_size;
51425bb815Sopenharmony_ci
52425bb815Sopenharmony_ci  if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
53425bb815Sopenharmony_ci  {
54425bb815Sopenharmony_ci    payload_p = JERRY_CONTEXT (debugger_send_buffer_payload_p);
55425bb815Sopenharmony_ci    max_send_size = JERRY_CONTEXT (debugger_max_send_size);
56425bb815Sopenharmony_ci    max_receive_size = JERRY_CONTEXT (debugger_max_receive_size);
57425bb815Sopenharmony_ci  }
58425bb815Sopenharmony_ci  else
59425bb815Sopenharmony_ci  {
60425bb815Sopenharmony_ci    JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_CONNECTED);
61425bb815Sopenharmony_ci    payload_p = JERRY_CONTEXT (debugger_send_buffer);
62425bb815Sopenharmony_ci    max_send_size = JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE;
63425bb815Sopenharmony_ci    max_receive_size = JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE;
64425bb815Sopenharmony_ci  }
65425bb815Sopenharmony_ci
66425bb815Sopenharmony_ci  JERRY_ASSERT (max_send_size > JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE + send_message_header_size);
67425bb815Sopenharmony_ci  JERRY_ASSERT (max_receive_size > JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE + receive_message_header_size);
68425bb815Sopenharmony_ci
69425bb815Sopenharmony_ci  JERRY_CONTEXT (debugger_send_buffer_payload_p) = payload_p + send_message_header_size;
70425bb815Sopenharmony_ci
71425bb815Sopenharmony_ci  max_send_size = max_send_size - send_message_header_size;
72425bb815Sopenharmony_ci  max_receive_size = max_receive_size - receive_message_header_size;
73425bb815Sopenharmony_ci
74425bb815Sopenharmony_ci  if (max_send_size > max_send_message_size)
75425bb815Sopenharmony_ci  {
76425bb815Sopenharmony_ci    max_send_size = max_send_message_size;
77425bb815Sopenharmony_ci  }
78425bb815Sopenharmony_ci
79425bb815Sopenharmony_ci  if (max_receive_size > max_receive_message_size)
80425bb815Sopenharmony_ci  {
81425bb815Sopenharmony_ci    max_receive_size = max_receive_message_size;
82425bb815Sopenharmony_ci  }
83425bb815Sopenharmony_ci
84425bb815Sopenharmony_ci  JERRY_CONTEXT (debugger_max_send_size) = (uint8_t) max_send_size;
85425bb815Sopenharmony_ci  JERRY_CONTEXT (debugger_max_receive_size) = (uint8_t) max_receive_size;
86425bb815Sopenharmony_ci} /* jerry_debugger_transport_add */
87425bb815Sopenharmony_ci
88425bb815Sopenharmony_ci/**
89425bb815Sopenharmony_ci * Starts the communication to the debugger client.
90425bb815Sopenharmony_ci * Must be called after the connection is successfully established.
91425bb815Sopenharmony_ci */
92425bb815Sopenharmony_civoid
93425bb815Sopenharmony_cijerry_debugger_transport_start (void)
94425bb815Sopenharmony_ci{
95425bb815Sopenharmony_ci#ifdef ACE_DEBUGGER_CUSTOM
96425bb815Sopenharmony_ci  JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_TRANSPORT_STARTED);
97425bb815Sopenharmony_ci#endif
98425bb815Sopenharmony_ci  JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
99425bb815Sopenharmony_ci
100425bb815Sopenharmony_ci  if (jerry_debugger_send_configuration (JERRY_CONTEXT (debugger_max_receive_size)))
101425bb815Sopenharmony_ci  {
102425bb815Sopenharmony_ci    JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP);
103425bb815Sopenharmony_ci    JERRY_CONTEXT (debugger_stop_context) = NULL;
104425bb815Sopenharmony_ci  }
105425bb815Sopenharmony_ci} /* jerry_debugger_transport_start */
106425bb815Sopenharmony_ci
107425bb815Sopenharmony_ci/**
108425bb815Sopenharmony_ci * Returns true if a debugger client is connected.
109425bb815Sopenharmony_ci *
110425bb815Sopenharmony_ci * @return true - a debugger client is connected,
111425bb815Sopenharmony_ci *         false - otherwise
112425bb815Sopenharmony_ci */
113425bb815Sopenharmony_cibool
114425bb815Sopenharmony_cijerry_debugger_transport_is_connected (void)
115425bb815Sopenharmony_ci{
116425bb815Sopenharmony_ci  return (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) != 0;
117425bb815Sopenharmony_ci} /* jerry_debugger_transport_is_connected */
118425bb815Sopenharmony_ci
119425bb815Sopenharmony_ci/**
120425bb815Sopenharmony_ci * Notifies the debugger server that the connection is closed.
121425bb815Sopenharmony_ci */
122425bb815Sopenharmony_civoid
123425bb815Sopenharmony_cijerry_debugger_transport_close (void)
124425bb815Sopenharmony_ci{
125425bb815Sopenharmony_ci  if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED))
126425bb815Sopenharmony_ci  {
127425bb815Sopenharmony_ci    return;
128425bb815Sopenharmony_ci  }
129425bb815Sopenharmony_ci
130425bb815Sopenharmony_ci  JERRY_CONTEXT (debugger_flags) = JERRY_DEBUGGER_VM_IGNORE;
131425bb815Sopenharmony_ci
132425bb815Sopenharmony_ci  jerry_debugger_transport_header_t *current_p = JERRY_CONTEXT (debugger_transport_header_p);
133425bb815Sopenharmony_ci
134425bb815Sopenharmony_ci  JERRY_ASSERT (current_p != NULL);
135425bb815Sopenharmony_ci
136425bb815Sopenharmony_ci  do
137425bb815Sopenharmony_ci  {
138425bb815Sopenharmony_ci    jerry_debugger_transport_header_t *next_p = current_p->next_p;
139425bb815Sopenharmony_ci
140425bb815Sopenharmony_ci    current_p->close (current_p);
141425bb815Sopenharmony_ci
142425bb815Sopenharmony_ci    current_p = next_p;
143425bb815Sopenharmony_ci  }
144425bb815Sopenharmony_ci  while (current_p != NULL);
145425bb815Sopenharmony_ci
146425bb815Sopenharmony_ci  jerry_port_log (JERRY_LOG_LEVEL_DEBUG, "Debugger client connection closed.\n");
147425bb815Sopenharmony_ci
148425bb815Sopenharmony_ci  jerry_debugger_free_unreferenced_byte_code ();
149425bb815Sopenharmony_ci} /* jerry_debugger_transport_close */
150425bb815Sopenharmony_ci
151425bb815Sopenharmony_ci/**
152425bb815Sopenharmony_ci * Send data over the current connection
153425bb815Sopenharmony_ci *
154425bb815Sopenharmony_ci * @return true - data sent successfully,
155425bb815Sopenharmony_ci *         false - connection closed
156425bb815Sopenharmony_ci */
157425bb815Sopenharmony_cibool
158425bb815Sopenharmony_cijerry_debugger_transport_send (const uint8_t *message_p, /**< message to be sent */
159425bb815Sopenharmony_ci                               size_t message_length) /**< message length in bytes */
160425bb815Sopenharmony_ci{
161425bb815Sopenharmony_ci  JERRY_ASSERT (jerry_debugger_transport_is_connected ());
162425bb815Sopenharmony_ci  JERRY_ASSERT (message_length > 0);
163425bb815Sopenharmony_ci
164425bb815Sopenharmony_ci  jerry_debugger_transport_header_t *header_p = JERRY_CONTEXT (debugger_transport_header_p);
165425bb815Sopenharmony_ci  uint8_t *payload_p = JERRY_CONTEXT (debugger_send_buffer_payload_p);
166425bb815Sopenharmony_ci  size_t max_send_size = JERRY_CONTEXT (debugger_max_send_size);
167425bb815Sopenharmony_ci
168425bb815Sopenharmony_ci  do
169425bb815Sopenharmony_ci  {
170425bb815Sopenharmony_ci    size_t fragment_length = (message_length <= max_send_size ? message_length
171425bb815Sopenharmony_ci                                                              : max_send_size);
172425bb815Sopenharmony_ci
173425bb815Sopenharmony_ci    memcpy (payload_p, message_p, fragment_length);
174425bb815Sopenharmony_ci
175425bb815Sopenharmony_ci    if (!header_p->send (header_p, payload_p, fragment_length))
176425bb815Sopenharmony_ci    {
177425bb815Sopenharmony_ci      return false;
178425bb815Sopenharmony_ci    }
179425bb815Sopenharmony_ci
180425bb815Sopenharmony_ci    message_p += fragment_length;
181425bb815Sopenharmony_ci    message_length -= fragment_length;
182425bb815Sopenharmony_ci  }
183425bb815Sopenharmony_ci  while (message_length > 0);
184425bb815Sopenharmony_ci
185425bb815Sopenharmony_ci  return true;
186425bb815Sopenharmony_ci} /* jerry_debugger_transport_send */
187425bb815Sopenharmony_ci
188425bb815Sopenharmony_ci/**
189425bb815Sopenharmony_ci * Receive data from the current connection
190425bb815Sopenharmony_ci *
191425bb815Sopenharmony_ci * Note:
192425bb815Sopenharmony_ci *   A message is received if message_start_p is not NULL
193425bb815Sopenharmony_ci *
194425bb815Sopenharmony_ci * @return true - function successfully completed,
195425bb815Sopenharmony_ci *         false - connection closed
196425bb815Sopenharmony_ci */
197425bb815Sopenharmony_cibool
198425bb815Sopenharmony_cijerry_debugger_transport_receive (jerry_debugger_transport_receive_context_t *context_p) /**< [out] receive
199425bb815Sopenharmony_ci                                                                                          *   context */
200425bb815Sopenharmony_ci{
201425bb815Sopenharmony_ci  JERRY_ASSERT (jerry_debugger_transport_is_connected ());
202425bb815Sopenharmony_ci
203425bb815Sopenharmony_ci  context_p->buffer_p = JERRY_CONTEXT (debugger_receive_buffer);
204425bb815Sopenharmony_ci  context_p->received_length = JERRY_CONTEXT (debugger_received_length);
205425bb815Sopenharmony_ci  context_p->message_p = NULL;
206425bb815Sopenharmony_ci  context_p->message_length = 0;
207425bb815Sopenharmony_ci  context_p->message_total_length = 0;
208425bb815Sopenharmony_ci
209425bb815Sopenharmony_ci  jerry_debugger_transport_header_t *header_p = JERRY_CONTEXT (debugger_transport_header_p);
210425bb815Sopenharmony_ci
211425bb815Sopenharmony_ci  return header_p->receive (header_p, context_p);
212425bb815Sopenharmony_ci} /* jerry_debugger_transport_receive */
213425bb815Sopenharmony_ci
214425bb815Sopenharmony_ci/**
215425bb815Sopenharmony_ci * Clear the message buffer after the message is processed
216425bb815Sopenharmony_ci */
217425bb815Sopenharmony_civoid
218425bb815Sopenharmony_cijerry_debugger_transport_receive_completed (jerry_debugger_transport_receive_context_t *context_p) /**< receive
219425bb815Sopenharmony_ci                                                                                                    *   context */
220425bb815Sopenharmony_ci{
221425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->message_p != NULL);
222425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->buffer_p == JERRY_CONTEXT (debugger_receive_buffer));
223425bb815Sopenharmony_ci
224425bb815Sopenharmony_ci  size_t message_total_length = context_p->message_total_length;
225425bb815Sopenharmony_ci  size_t received_length = context_p->received_length;
226425bb815Sopenharmony_ci
227425bb815Sopenharmony_ci  JERRY_ASSERT (message_total_length <= received_length);
228425bb815Sopenharmony_ci
229425bb815Sopenharmony_ci  if (message_total_length == 0 || message_total_length == received_length)
230425bb815Sopenharmony_ci  {
231425bb815Sopenharmony_ci    /* All received data is processed. */
232425bb815Sopenharmony_ci    JERRY_CONTEXT (debugger_received_length) = 0;
233425bb815Sopenharmony_ci    return;
234425bb815Sopenharmony_ci  }
235425bb815Sopenharmony_ci
236425bb815Sopenharmony_ci  uint8_t *buffer_p = context_p->buffer_p;
237425bb815Sopenharmony_ci  received_length -= message_total_length;
238425bb815Sopenharmony_ci
239425bb815Sopenharmony_ci  memmove (buffer_p, buffer_p + message_total_length, received_length);
240425bb815Sopenharmony_ci
241425bb815Sopenharmony_ci  JERRY_CONTEXT (debugger_received_length) = (uint16_t) received_length;
242425bb815Sopenharmony_ci} /* jerry_debugger_transport_receive_completed */
243425bb815Sopenharmony_ci
244425bb815Sopenharmony_ci/**
245425bb815Sopenharmony_ci * Suspend execution for a predefined time (JERRY_DEBUGGER_TRANSPORT_TIMEOUT ms).
246425bb815Sopenharmony_ci */
247425bb815Sopenharmony_civoid
248425bb815Sopenharmony_cijerry_debugger_transport_sleep (void)
249425bb815Sopenharmony_ci{
250425bb815Sopenharmony_ci  jerry_port_sleep (JERRY_DEBUGGER_TRANSPORT_TIMEOUT);
251425bb815Sopenharmony_ci} /* jerry_debugger_transport_sleep */
252425bb815Sopenharmony_ci
253425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_DEBUGGER) */
254