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 "jerryscript-ext/debugger.h" |
17 | #include "jext-common.h" |
18 | |
19 | #if defined (JERRY_DEBUGGER) && (JERRY_DEBUGGER == 1) |
20 | |
21 | /* A simplified transmission layer. */ |
22 | |
23 | /** |
24 | * Size of the raw packet header. |
25 | */ |
26 | #define JERRYX_DEBUGGER_RAWPACKET_HEADER_SIZE 1 |
27 | /** |
28 | * Maximum message size with 1 byte size field. |
29 | */ |
30 | #define JERRYX_DEBUGGER_RAWPACKET_ONE_BYTE_LEN_MAX 255 |
31 | |
32 | /** |
33 | * Header for incoming packets. |
34 | */ |
35 | typedef struct |
36 | { |
37 | uint8_t size; /**< size of the message */ |
38 | } jerryx_rawpacket_receive_header_t; |
39 | |
40 | /** |
41 | * Close a tcp connection. |
42 | */ |
43 | static void |
44 | jerryx_debugger_rp_close (jerry_debugger_transport_header_t *header_p) /**< header for the transport interface */ |
45 | { |
46 | JERRYX_ASSERT (!jerry_debugger_transport_is_connected ()); |
47 | |
48 | jerry_heap_free ((void *) header_p, sizeof (jerry_debugger_transport_header_t)); |
49 | } /* jerryx_debugger_rp_close */ |
50 | |
51 | /** |
52 | * Send data over a simple raw packet connection. |
53 | * |
54 | * @return true - if the data has been sent successfully |
55 | * false - otherwise |
56 | */ |
57 | static bool |
58 | jerryx_debugger_rp_send (jerry_debugger_transport_header_t *header_p, /**< header for the transport interface */ |
59 | uint8_t *message_p, /**< message to be sent */ |
60 | size_t message_length) /**< message length in bytes */ |
61 | { |
62 | JERRYX_ASSERT (message_length <= JERRYX_DEBUGGER_RAWPACKET_ONE_BYTE_LEN_MAX); |
63 | |
64 | message_p[-1] = (uint8_t) message_length; |
65 | |
66 | return header_p->next_p->send (header_p->next_p, message_p - 1, message_length + 1); |
67 | } /* jerryx_debugger_rp_send */ |
68 | |
69 | /** |
70 | * Receive data from a rawpacket connection. |
71 | * |
72 | * @return true - if data has been received successfully |
73 | * false - otherwise |
74 | */ |
75 | static bool |
76 | jerryx_debugger_rp_receive (jerry_debugger_transport_header_t *header_p, /**< header for the transport interface */ |
77 | jerry_debugger_transport_receive_context_t *receive_context_p) /**< receive context */ |
78 | { |
79 | if (!header_p->next_p->receive (header_p->next_p, receive_context_p)) |
80 | { |
81 | return false; |
82 | } |
83 | |
84 | if (receive_context_p->message_p == NULL) |
85 | { |
86 | return true; |
87 | } |
88 | |
89 | size_t message_total_length = receive_context_p->message_total_length; |
90 | |
91 | if (message_total_length == 0) |
92 | { |
93 | /* Byte stream. */ |
94 | if (receive_context_p->message_length < sizeof (jerryx_rawpacket_receive_header_t)) |
95 | { |
96 | receive_context_p->message_p = NULL; |
97 | return true; |
98 | } |
99 | } |
100 | else |
101 | { |
102 | /* Datagram packet. */ |
103 | JERRYX_ASSERT (receive_context_p->message_length >= sizeof (jerryx_rawpacket_receive_header_t)); |
104 | } |
105 | |
106 | uint8_t *message_p = receive_context_p->message_p; |
107 | size_t message_length = (size_t) (message_p[0]); |
108 | |
109 | if (message_total_length == 0) |
110 | { |
111 | size_t new_total_length = message_length + sizeof (jerryx_rawpacket_receive_header_t); |
112 | |
113 | /* Byte stream. */ |
114 | if (receive_context_p->message_length < new_total_length) |
115 | { |
116 | receive_context_p->message_p = NULL; |
117 | return true; |
118 | } |
119 | |
120 | receive_context_p->message_total_length = new_total_length; |
121 | } |
122 | else |
123 | { |
124 | /* Datagram packet. */ |
125 | JERRYX_ASSERT (receive_context_p->message_length == (message_length + sizeof (jerryx_rawpacket_receive_header_t))); |
126 | } |
127 | |
128 | receive_context_p->message_p = message_p + sizeof (jerryx_rawpacket_receive_header_t); |
129 | receive_context_p->message_length = message_length; |
130 | |
131 | return true; |
132 | } /* jerryx_debugger_rp_receive */ |
133 | |
134 | /** |
135 | * Initialize a simple raw packet transmission layer. |
136 | * |
137 | * @return true - if the connection succeeded |
138 | * false - otherwise |
139 | */ |
140 | bool |
141 | jerryx_debugger_rp_create (void) |
142 | { |
143 | const size_t interface_size = sizeof (jerry_debugger_transport_header_t); |
144 | jerry_debugger_transport_header_t *header_p; |
145 | header_p = (jerry_debugger_transport_header_t *) jerry_heap_alloc (interface_size); |
146 | |
147 | if (!header_p) |
148 | { |
149 | return false; |
150 | } |
151 | |
152 | header_p->close = jerryx_debugger_rp_close; |
153 | header_p->send = jerryx_debugger_rp_send; |
154 | header_p->receive = jerryx_debugger_rp_receive; |
155 | |
156 | jerry_debugger_transport_add (header_p, |
157 | JERRYX_DEBUGGER_RAWPACKET_HEADER_SIZE, |
158 | JERRYX_DEBUGGER_RAWPACKET_ONE_BYTE_LEN_MAX, |
159 | JERRYX_DEBUGGER_RAWPACKET_HEADER_SIZE, |
160 | JERRYX_DEBUGGER_RAWPACKET_ONE_BYTE_LEN_MAX); |
161 | |
162 | return true; |
163 | } /* jerryx_debugger_rp_create */ |
164 | |
165 | #else /* !(defined (JERRY_DEBUGGER) && (JERRY_DEBUGGER == 1)) */ |
166 | |
167 | /** |
168 | * Dummy function when debugger is disabled. |
169 | * |
170 | * @return false |
171 | */ |
172 | bool |
173 | jerryx_debugger_rp_create (void) |
174 | { |
175 | return false; |
176 | } /* jerryx_debugger_rp_create */ |
177 | |
178 | #endif /* defined (JERRY_DEBUGGER) && (JERRY_DEBUGGER == 1) */ |
179 | |