• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright JS Foundation and other contributors, http://js.foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "debugger.h"
17 #include "jcontext.h"
18 #include "jerryscript.h"
19 
20 #if ENABLED (JERRY_DEBUGGER)
21 
22 /**
23  * Minimum number of bytes transmitted or received.
24  */
25 #define JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE 64
26 
27 /**
28  * Sleep time in milliseconds between each jerry_debugger_receive call
29  */
30 #define JERRY_DEBUGGER_TRANSPORT_TIMEOUT 10
31 
32 /**
33  * Add a new transport layer.
34  */
35 void
jerry_debugger_transport_add(jerry_debugger_transport_header_t * header_p,size_t send_message_header_size,size_t max_send_message_size,size_t receive_message_header_size,size_t max_receive_message_size)36 jerry_debugger_transport_add (jerry_debugger_transport_header_t *header_p, /**< transport implementation */
37                               size_t send_message_header_size, /**< header bytes reserved for outgoing messages */
38                               size_t max_send_message_size, /**< maximum number of bytes transmitted in a message */
39                               size_t receive_message_header_size, /**< header bytes reserved for incoming messages */
40                               size_t max_receive_message_size) /**< maximum number of bytes received in a message */
41 {
42   JERRY_ASSERT (max_send_message_size > JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE
43                 && max_receive_message_size > JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE);
44 
45   header_p->next_p = JERRY_CONTEXT (debugger_transport_header_p);
46   JERRY_CONTEXT (debugger_transport_header_p) = header_p;
47 
48   uint8_t *payload_p;
49   size_t max_send_size;
50   size_t max_receive_size;
51 
52   if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
53   {
54     payload_p = JERRY_CONTEXT (debugger_send_buffer_payload_p);
55     max_send_size = JERRY_CONTEXT (debugger_max_send_size);
56     max_receive_size = JERRY_CONTEXT (debugger_max_receive_size);
57   }
58   else
59   {
60     JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_CONNECTED);
61     payload_p = JERRY_CONTEXT (debugger_send_buffer);
62     max_send_size = JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE;
63     max_receive_size = JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE;
64   }
65 
66   JERRY_ASSERT (max_send_size > JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE + send_message_header_size);
67   JERRY_ASSERT (max_receive_size > JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE + receive_message_header_size);
68 
69   JERRY_CONTEXT (debugger_send_buffer_payload_p) = payload_p + send_message_header_size;
70 
71   max_send_size = max_send_size - send_message_header_size;
72   max_receive_size = max_receive_size - receive_message_header_size;
73 
74   if (max_send_size > max_send_message_size)
75   {
76     max_send_size = max_send_message_size;
77   }
78 
79   if (max_receive_size > max_receive_message_size)
80   {
81     max_receive_size = max_receive_message_size;
82   }
83 
84   JERRY_CONTEXT (debugger_max_send_size) = (uint8_t) max_send_size;
85   JERRY_CONTEXT (debugger_max_receive_size) = (uint8_t) max_receive_size;
86 } /* jerry_debugger_transport_add */
87 
88 /**
89  * Starts the communication to the debugger client.
90  * Must be called after the connection is successfully established.
91  */
92 void
jerry_debugger_transport_start(void)93 jerry_debugger_transport_start (void)
94 {
95 #ifdef ACE_DEBUGGER_CUSTOM
96   JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_TRANSPORT_STARTED);
97 #endif
98   JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
99 
100   if (jerry_debugger_send_configuration (JERRY_CONTEXT (debugger_max_receive_size)))
101   {
102     JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP);
103     JERRY_CONTEXT (debugger_stop_context) = NULL;
104   }
105 } /* jerry_debugger_transport_start */
106 
107 /**
108  * Returns true if a debugger client is connected.
109  *
110  * @return true - a debugger client is connected,
111  *         false - otherwise
112  */
113 bool
jerry_debugger_transport_is_connected(void)114 jerry_debugger_transport_is_connected (void)
115 {
116   return (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) != 0;
117 } /* jerry_debugger_transport_is_connected */
118 
119 /**
120  * Notifies the debugger server that the connection is closed.
121  */
122 void
jerry_debugger_transport_close(void)123 jerry_debugger_transport_close (void)
124 {
125   if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED))
126   {
127     return;
128   }
129 
130   JERRY_CONTEXT (debugger_flags) = JERRY_DEBUGGER_VM_IGNORE;
131 
132   jerry_debugger_transport_header_t *current_p = JERRY_CONTEXT (debugger_transport_header_p);
133 
134   JERRY_ASSERT (current_p != NULL);
135 
136   do
137   {
138     jerry_debugger_transport_header_t *next_p = current_p->next_p;
139 
140     current_p->close (current_p);
141 
142     current_p = next_p;
143   }
144   while (current_p != NULL);
145 
146   jerry_port_log (JERRY_LOG_LEVEL_DEBUG, "Debugger client connection closed.\n");
147 
148   jerry_debugger_free_unreferenced_byte_code ();
149 } /* jerry_debugger_transport_close */
150 
151 /**
152  * Send data over the current connection
153  *
154  * @return true - data sent successfully,
155  *         false - connection closed
156  */
157 bool
jerry_debugger_transport_send(const uint8_t * message_p,size_t message_length)158 jerry_debugger_transport_send (const uint8_t *message_p, /**< message to be sent */
159                                size_t message_length) /**< message length in bytes */
160 {
161   JERRY_ASSERT (jerry_debugger_transport_is_connected ());
162   JERRY_ASSERT (message_length > 0);
163 
164   jerry_debugger_transport_header_t *header_p = JERRY_CONTEXT (debugger_transport_header_p);
165   uint8_t *payload_p = JERRY_CONTEXT (debugger_send_buffer_payload_p);
166   size_t max_send_size = JERRY_CONTEXT (debugger_max_send_size);
167 
168   do
169   {
170     size_t fragment_length = (message_length <= max_send_size ? message_length
171                                                               : max_send_size);
172 
173     memcpy (payload_p, message_p, fragment_length);
174 
175     if (!header_p->send (header_p, payload_p, fragment_length))
176     {
177       return false;
178     }
179 
180     message_p += fragment_length;
181     message_length -= fragment_length;
182   }
183   while (message_length > 0);
184 
185   return true;
186 } /* jerry_debugger_transport_send */
187 
188 /**
189  * Receive data from the current connection
190  *
191  * Note:
192  *   A message is received if message_start_p is not NULL
193  *
194  * @return true - function successfully completed,
195  *         false - connection closed
196  */
197 bool
jerry_debugger_transport_receive(jerry_debugger_transport_receive_context_t * context_p)198 jerry_debugger_transport_receive (jerry_debugger_transport_receive_context_t *context_p) /**< [out] receive
199                                                                                           *   context */
200 {
201   JERRY_ASSERT (jerry_debugger_transport_is_connected ());
202 
203   context_p->buffer_p = JERRY_CONTEXT (debugger_receive_buffer);
204   context_p->received_length = JERRY_CONTEXT (debugger_received_length);
205   context_p->message_p = NULL;
206   context_p->message_length = 0;
207   context_p->message_total_length = 0;
208 
209   jerry_debugger_transport_header_t *header_p = JERRY_CONTEXT (debugger_transport_header_p);
210 
211   return header_p->receive (header_p, context_p);
212 } /* jerry_debugger_transport_receive */
213 
214 /**
215  * Clear the message buffer after the message is processed
216  */
217 void
jerry_debugger_transport_receive_completed(jerry_debugger_transport_receive_context_t * context_p)218 jerry_debugger_transport_receive_completed (jerry_debugger_transport_receive_context_t *context_p) /**< receive
219                                                                                                     *   context */
220 {
221   JERRY_ASSERT (context_p->message_p != NULL);
222   JERRY_ASSERT (context_p->buffer_p == JERRY_CONTEXT (debugger_receive_buffer));
223 
224   size_t message_total_length = context_p->message_total_length;
225   size_t received_length = context_p->received_length;
226 
227   JERRY_ASSERT (message_total_length <= received_length);
228 
229   if (message_total_length == 0 || message_total_length == received_length)
230   {
231     /* All received data is processed. */
232     JERRY_CONTEXT (debugger_received_length) = 0;
233     return;
234   }
235 
236   uint8_t *buffer_p = context_p->buffer_p;
237   received_length -= message_total_length;
238 
239   memmove (buffer_p, buffer_p + message_total_length, received_length);
240 
241   JERRY_CONTEXT (debugger_received_length) = (uint16_t) received_length;
242 } /* jerry_debugger_transport_receive_completed */
243 
244 /**
245  * Suspend execution for a predefined time (JERRY_DEBUGGER_TRANSPORT_TIMEOUT ms).
246  */
247 void
jerry_debugger_transport_sleep(void)248 jerry_debugger_transport_sleep (void)
249 {
250   jerry_port_sleep (JERRY_DEBUGGER_TRANSPORT_TIMEOUT);
251 } /* jerry_debugger_transport_sleep */
252 
253 #endif /* ENABLED (JERRY_DEBUGGER) */
254