xref: /btstack/src/classic/goep_server.c (revision 1ce6ee5534081e3952388bfcc1d718d53b4ea223)
1 /*
2  * Copyright (C) 2019 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 #define BTSTACK_FILE__ "goep_server.c"
39 
40 #include "btstack_config.h"
41 
42 #include <stdint.h>
43 #include <string.h>
44 
45 #include "hci_cmd.h"
46 #include "btstack_debug.h"
47 #include "btstack_defines.h"
48 #include "hci.h"
49 #include "btstack_memory.h"
50 #include "hci_dump.h"
51 #include "btstack_event.h"
52 
53 #include "classic/goep_server.h"
54 #include "classic/obex.h"
55 #include "classic/obex_message_builder.h"
56 
57 #ifdef ENABLE_GOEP_L2CAP
58 #include "l2cap.h"
59 
60 static l2cap_ertm_config_t ertm_config = {
61     1,  // ertm mandatory
62     2,  // max transmit, some tests require > 1
63     2000,
64     12000,
65     (GOEP_SERVER_ERTM_BUFFER / 2),    // l2cap ertm mtu
66     4,
67     4,
68     1,      // 16-bit FCS
69 };
70 
71 static uint8_t goep_server_l2cap_packet_buffer[GOEP_SERVER_ERTM_BUFFER];
72 
73 #endif
74 
75 static btstack_linked_list_t goep_server_connections = NULL;
76 static btstack_linked_list_t goep_server_services = NULL;
77 static uint16_t goep_server_cid_counter = 0;
78 
79 static goep_server_service_t * goep_server_get_service_for_rfcomm_channel(uint8_t rfcomm_channel){
80     btstack_linked_item_t *it;
81     for (it = (btstack_linked_item_t *) goep_server_services; it ; it = it->next){
82         goep_server_service_t * service = ((goep_server_service_t *) it);
83         if (service->rfcomm_channel == rfcomm_channel){
84             return service;
85         };
86     }
87     return NULL;
88 }
89 
90 #ifdef ENABLE_GOEP_L2CAP
91 static goep_server_service_t * goep_server_get_service_for_l2cap_psm(uint16_t l2cap_psm){
92     btstack_linked_item_t *it;
93     for (it = (btstack_linked_item_t *) goep_server_services; it ; it = it->next){
94         goep_server_service_t * service = ((goep_server_service_t *) it);
95         if (service->l2cap_psm == l2cap_psm){
96             return service;
97         };
98     }
99     return NULL;
100 }
101 #endif
102 
103 static goep_server_connection_t * goep_server_get_connection_for_rfcomm_cid(uint16_t bearer_cid){
104     btstack_linked_item_t *it;
105     for (it = (btstack_linked_item_t *) goep_server_connections; it ; it = it->next){
106         goep_server_connection_t * connection = ((goep_server_connection_t *) it);
107         if (connection->type != GOEP_CONNECTION_RFCOMM) continue;
108         if (connection->bearer_cid == bearer_cid){
109             return connection;
110         };
111     }
112     return NULL;
113 }
114 
115 #ifdef ENABLE_GOEP_L2CAP
116 static goep_server_connection_t * goep_server_get_connection_for_l2cap_cid(uint16_t bearer_cid){
117     btstack_linked_item_t *it;
118     for (it = (btstack_linked_item_t *) goep_server_connections; it ; it = it->next){
119         goep_server_connection_t * connection = ((goep_server_connection_t *) it);
120         if (connection->type != GOEP_CONNECTION_L2CAP) continue;
121         if (connection->bearer_cid == bearer_cid){
122             return connection;
123         };
124     }
125     return NULL;
126 }
127 #endif
128 
129 static goep_server_connection_t * goep_server_get_connection_for_goep_cid(uint16_t goep_cid){
130     btstack_linked_item_t *it;
131     for (it = (btstack_linked_item_t *) goep_server_connections; it ; it = it->next){
132         goep_server_connection_t * connection = ((goep_server_connection_t *) it);
133         if (connection->goep_cid == goep_cid){
134             return connection;
135         };
136     }
137     return NULL;
138 }
139 
140 static uint16_t goep_server_get_next_goep_cid(void){
141     goep_server_cid_counter++;
142     if (goep_server_cid_counter == 0){
143         goep_server_cid_counter = 1;
144     }
145     return goep_server_cid_counter;
146 }
147 
148 static inline void goep_server_emit_incoming_connection(btstack_packet_handler_t callback, uint16_t goep_cid, bd_addr_t bd_addr, hci_con_handle_t con_handle){
149     uint8_t event[13];
150     uint16_t pos = 0;
151     event[pos++] = HCI_EVENT_GOEP_META;
152     event[pos++] = 15 - 2;
153     event[pos++] = GOEP_SUBEVENT_INCOMING_CONNECTION;
154     little_endian_store_16(event, pos, goep_cid);
155     pos+=2;
156     reverse_bd_addr(bd_addr, &event[pos]);
157     pos += 6;
158     little_endian_store_16(event, pos, con_handle);
159     pos += 2;
160     btstack_assert(pos == sizeof(event));
161     callback(HCI_EVENT_PACKET, goep_cid, &event[0], pos);
162 }
163 
164 static inline void goep_server_emit_connection_opened(btstack_packet_handler_t callback, uint16_t goep_cid, bd_addr_t bd_addr, hci_con_handle_t con_handle, uint8_t status){
165     uint8_t event[15];
166     uint16_t pos = 0;
167     event[pos++] = HCI_EVENT_GOEP_META;
168     event[pos++] = 15 - 2;
169     event[pos++] = GOEP_SUBEVENT_CONNECTION_OPENED;
170     little_endian_store_16(event, pos, goep_cid);
171     pos+=2;
172     event[pos++] = status;
173     reverse_bd_addr(bd_addr, &event[pos]);
174     pos += 6;
175     little_endian_store_16(event, pos, con_handle);
176     pos += 2;
177     event[pos++] = 1;
178     btstack_assert(pos == sizeof(event));
179     callback(HCI_EVENT_PACKET, goep_cid, &event[0], pos);
180 }
181 
182 static inline void goep_server_emit_connection_closed(btstack_packet_handler_t callback, uint16_t goep_cid){
183     uint8_t event[5];
184     uint16_t pos = 0;
185     event[pos++] = HCI_EVENT_GOEP_META;
186     event[pos++] = 5 - 3;
187     event[pos++] = GOEP_SUBEVENT_CONNECTION_CLOSED;
188     little_endian_store_16(event, pos, goep_cid);
189     pos += 2;
190     btstack_assert(pos == sizeof(event));
191     callback(HCI_EVENT_PACKET, goep_cid, &event[0], pos);
192 }
193 
194 static inline void goep_server_emit_can_send_now_event(goep_server_connection_t * connection){
195     uint8_t event[5];
196     uint16_t pos = 0;
197     event[pos++] = HCI_EVENT_GOEP_META;
198     event[pos++] = 5 - 3;
199     event[pos++] = GOEP_SUBEVENT_CAN_SEND_NOW;
200     little_endian_store_16(event,pos,connection->goep_cid);
201     pos += 2;
202     btstack_assert(pos == sizeof(event));
203     connection->callback(HCI_EVENT_PACKET, connection->goep_cid, &event[0], pos);
204 }
205 
206 static void goep_server_handle_connection_opened(goep_server_connection_t * context, bd_addr_t addr, hci_con_handle_t con_handle, uint8_t status, uint16_t bearer_cid, uint16_t bearer_mtu){
207 
208     uint16_t goep_cid = context->goep_cid;
209     btstack_packet_handler_t packet_handler = context->callback;
210 
211     if (status) {
212         log_info("goep_client: open failed, status %u", status);
213         btstack_linked_list_remove(&goep_server_connections, (btstack_linked_item_t *) context);
214         btstack_memory_goep_server_connection_free(context);
215     } else {
216         // context->bearer_mtu = mtu;
217         context->state = GOEP_SERVER_CONNECTED;
218         context->bearer_cid = bearer_cid;
219 #ifdef ENABLE_GOEP_L2CAP
220         if (context->type == GOEP_CONNECTION_L2CAP){
221             bearer_mtu = btstack_min(bearer_mtu, sizeof(goep_server_l2cap_packet_buffer));
222         }
223 #endif
224         context->bearer_mtu = bearer_mtu;
225         log_info("goep_server: connection opened. cid %u, max frame size %u", context->bearer_cid, bearer_mtu);
226     }
227 
228     goep_server_emit_connection_opened(packet_handler, goep_cid, addr, con_handle, status);
229 }
230 
231 static void goep_server_handle_connection_closed(goep_server_connection_t * goep_connection){
232     uint16_t goep_cid = goep_connection->goep_cid;
233     btstack_packet_handler_t packet_handler = goep_connection->callback;
234 
235     btstack_linked_list_remove(&goep_server_connections, (btstack_linked_item_t *) goep_connection);
236     btstack_memory_goep_server_connection_free(goep_connection);
237 
238     goep_server_emit_connection_closed(packet_handler, goep_cid);
239 }
240 
241 #ifdef ENABLE_GOEP_L2CAP
242 static void goep_server_packet_handler_l2cap(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
243     UNUSED(channel);
244     UNUSED(size);
245 
246     bd_addr_t event_addr;
247     uint16_t l2cap_psm;
248     uint16_t l2cap_cid;
249     goep_server_connection_t * goep_connection;
250     goep_server_service_t *    goep_service;
251 
252     switch (packet_type){
253         case HCI_EVENT_PACKET:
254             switch (hci_event_packet_get_type(packet)) {
255                 case L2CAP_EVENT_INCOMING_CONNECTION:
256                     l2cap_psm = l2cap_event_incoming_connection_get_psm(packet);
257                     l2cap_cid  = l2cap_event_incoming_connection_get_local_cid(packet);
258                     goep_service = goep_server_get_service_for_l2cap_psm(l2cap_psm);
259                     if (!goep_service){
260                         l2cap_decline_connection(l2cap_cid);
261                         break;
262                     }
263 
264                     // alloc structure
265                     goep_connection = btstack_memory_goep_server_connection_get();
266                     if (!goep_connection){
267                         l2cap_decline_connection(l2cap_cid);
268                         break;
269                     }
270 
271                     // setup connection
272                     goep_connection->goep_cid   = goep_server_get_next_goep_cid();
273                     goep_connection->bearer_cid = l2cap_cid;
274                     goep_connection->callback   = goep_service->callback;
275                     goep_connection->type       = GOEP_CONNECTION_L2CAP;
276                     goep_connection->state      = GOEP_SERVER_W4_ACCEPT_REJECT;
277                     btstack_linked_list_add(&goep_server_connections, (btstack_linked_item_t *) goep_connection);
278 
279                     // notify user
280                     l2cap_event_incoming_connection_get_address(packet, event_addr);
281                     goep_server_emit_incoming_connection(goep_service->callback, goep_connection->goep_cid, event_addr,
282                                                          l2cap_event_incoming_connection_get_handle(packet));
283                     break;
284 
285                 case L2CAP_EVENT_CHANNEL_OPENED:
286                     l2cap_cid = l2cap_event_channel_opened_get_local_cid(packet);
287                     goep_connection = goep_server_get_connection_for_l2cap_cid(l2cap_cid);
288                     btstack_assert(goep_connection != NULL);
289                     btstack_assert(goep_connection->state == GOEP_SERVER_W4_CONNECTED);
290                     l2cap_event_channel_opened_get_address(packet, event_addr);
291                     goep_server_handle_connection_opened(goep_connection, event_addr,
292                                                          l2cap_event_channel_opened_get_handle(packet),
293                                                          l2cap_event_channel_opened_get_status(packet),
294                                                          l2cap_cid,
295                                                          l2cap_event_channel_opened_get_remote_mtu(packet) );
296                     return;
297                 case L2CAP_EVENT_CAN_SEND_NOW:
298                     l2cap_cid = l2cap_event_can_send_now_get_local_cid(packet);
299                     goep_connection = goep_server_get_connection_for_l2cap_cid(l2cap_cid);
300                     btstack_assert(goep_connection != NULL);
301                     goep_server_emit_can_send_now_event(goep_connection);
302                     break;
303                 case L2CAP_EVENT_CHANNEL_CLOSED:
304                     l2cap_cid = l2cap_event_channel_closed_get_local_cid(packet);
305                     goep_connection = goep_server_get_connection_for_l2cap_cid(l2cap_cid);
306                     btstack_assert(goep_connection != NULL);
307                     goep_server_handle_connection_closed(goep_connection);
308                     break;
309                 default:
310                     break;
311             }
312             break;
313         case L2CAP_DATA_PACKET:
314             goep_connection = goep_server_get_connection_for_l2cap_cid(channel);
315             btstack_assert(goep_connection != NULL);
316             goep_connection->callback(GOEP_DATA_PACKET, goep_connection->goep_cid, packet, size);
317             break;
318         default:
319             break;
320     }
321 }
322 #endif
323 
324 static void goep_server_packet_handler_rfcomm(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
325     UNUSED(channel);
326     UNUSED(size);
327 
328     bd_addr_t event_addr;
329     uint8_t  rfcomm_channel;
330     uint16_t rfcomm_cid;
331     goep_server_service_t    * goep_service;
332     goep_server_connection_t * goep_connection;
333 
334     switch (packet_type){
335         case HCI_EVENT_PACKET:
336             switch (hci_event_packet_get_type(packet)) {
337                 case RFCOMM_EVENT_INCOMING_CONNECTION:
338                     rfcomm_channel = rfcomm_event_incoming_connection_get_server_channel(packet);
339                     rfcomm_cid = rfcomm_event_incoming_connection_get_rfcomm_cid(packet);
340 
341                     goep_service = goep_server_get_service_for_rfcomm_channel(rfcomm_channel);
342                     if (!goep_service){
343                         rfcomm_decline_connection(rfcomm_cid);
344                         break;
345                     }
346 
347                     // alloc structure
348                     goep_connection = btstack_memory_goep_server_connection_get();
349                     if (!goep_connection){
350                         rfcomm_decline_connection(rfcomm_cid);
351                         break;
352                     }
353 
354                     // setup connection
355                     goep_connection->goep_cid   = goep_server_get_next_goep_cid();
356                     goep_connection->bearer_cid = rfcomm_cid;
357                     goep_connection->callback   = goep_service->callback;
358                     goep_connection->type       = GOEP_CONNECTION_RFCOMM;
359                     goep_connection->state      = GOEP_SERVER_W4_ACCEPT_REJECT;
360                     btstack_linked_list_add(&goep_server_connections, (btstack_linked_item_t *) goep_connection);
361 
362                     // notify user
363                     rfcomm_event_incoming_connection_get_bd_addr(packet, event_addr);
364                     goep_server_emit_incoming_connection(goep_service->callback, goep_connection->goep_cid, event_addr,
365                                                          rfcomm_event_incoming_connection_get_con_handle(packet));
366                     break;
367 
368                 case RFCOMM_EVENT_CHANNEL_OPENED:
369                     rfcomm_cid = rfcomm_event_channel_opened_get_rfcomm_cid(packet);
370                     goep_connection = goep_server_get_connection_for_rfcomm_cid(rfcomm_cid);
371                     btstack_assert(goep_connection != NULL);
372                     btstack_assert(goep_connection->state == GOEP_SERVER_W4_CONNECTED);
373                     rfcomm_event_channel_opened_get_bd_addr(packet, event_addr);
374                     goep_server_handle_connection_opened(goep_connection, event_addr,
375                                                          rfcomm_event_channel_opened_get_con_handle(packet),
376                                                          rfcomm_event_channel_opened_get_status(packet),
377                                                          rfcomm_cid,
378                                                          rfcomm_event_channel_opened_get_max_frame_size(packet) );
379                     break;
380 
381                 case RFCOMM_EVENT_CAN_SEND_NOW:
382                     rfcomm_cid = rfcomm_event_can_send_now_get_rfcomm_cid(packet);
383                     goep_connection = goep_server_get_connection_for_rfcomm_cid(rfcomm_cid);
384                     btstack_assert(goep_connection != NULL);
385                     goep_server_emit_can_send_now_event(goep_connection);
386                     break;
387 
388                 case RFCOMM_EVENT_CHANNEL_CLOSED:
389                     rfcomm_cid = rfcomm_event_channel_closed_get_rfcomm_cid(packet);
390                     goep_connection = goep_server_get_connection_for_rfcomm_cid(rfcomm_cid);
391                     btstack_assert(goep_connection != NULL);
392                     goep_server_handle_connection_closed(goep_connection);
393                     break;
394 
395                 default:
396                     break;
397             }
398             break;
399 
400         case RFCOMM_DATA_PACKET:
401             goep_connection = goep_server_get_connection_for_rfcomm_cid(channel);
402             btstack_assert(goep_connection != NULL);
403             goep_connection->callback(GOEP_DATA_PACKET, goep_connection->goep_cid, packet, size);
404             break;
405 
406         default:
407             break;
408     }
409 }
410 
411 void goep_server_init(void){
412 }
413 
414 uint8_t goep_server_register_service(btstack_packet_handler_t callback, uint8_t rfcomm_channel, uint16_t rfcomm_max_frame_size,
415                 uint16_t l2cap_psm, uint16_t l2cap_mtu, gap_security_level_t security_level){
416 
417     log_info("rfcomm_channel 0x%02x rfcomm_max_frame_size %u l2cap_psm 0x%02x l2cap_mtu %u",
418              rfcomm_channel, rfcomm_max_frame_size, l2cap_psm, l2cap_mtu);
419 
420     // check if service is already registered
421     goep_server_service_t * service;
422     service = goep_server_get_service_for_rfcomm_channel(rfcomm_channel);
423     if (service != NULL) {
424         return RFCOMM_CHANNEL_ALREADY_REGISTERED;
425     }
426 
427 #ifdef ENABLE_GOEP_L2CAP
428     if (l2cap_psm != 0){
429         service = goep_server_get_service_for_l2cap_psm(l2cap_psm);
430         if (service != NULL) {
431             return L2CAP_SERVICE_ALREADY_REGISTERED;
432         }
433     }
434 #else
435     UNUSED(l2cap_mtu);
436     UNUSED(l2cap_psm);
437     UNUSED(security_level);
438 #endif
439 
440     // alloc structure
441     service = btstack_memory_goep_server_service_get();
442     if (service == NULL) {
443         return BTSTACK_MEMORY_ALLOC_FAILED;
444     }
445 
446     // fill in
447     service->callback = callback;
448     service->rfcomm_channel = rfcomm_channel;
449     service->l2cap_psm = l2cap_psm;
450 
451     uint8_t status = ERROR_CODE_SUCCESS;
452     bool rfcomm_registered = false;
453 
454 #ifdef ENABLE_GOEP_L2CAP
455     bool l2cap_registered = false;
456     // register with L2CAP
457     if (l2cap_psm != 0){
458         status = l2cap_register_service(goep_server_packet_handler_l2cap, l2cap_psm, l2cap_mtu, security_level);
459         if (status == ERROR_CODE_SUCCESS){
460             l2cap_registered = true;
461         }
462     }
463 #endif
464 
465     // register with RFCOMM
466     if (status == ERROR_CODE_SUCCESS){
467         status = rfcomm_register_service(goep_server_packet_handler_rfcomm, rfcomm_channel, rfcomm_max_frame_size);
468         if (status == ERROR_CODE_SUCCESS){
469             rfcomm_registered = true;
470         }
471     }
472 
473     // add service on success
474     if (status == ERROR_CODE_SUCCESS){
475         btstack_linked_list_add(&goep_server_services, (btstack_linked_item_t *) service);
476         return ERROR_CODE_SUCCESS;
477     }
478 
479     // unrestore otherwise
480     btstack_memory_goep_server_service_free(service);
481 #ifdef ENABLE_GOEP_L2CAP
482     if (l2cap_registered){
483         l2cap_unregister_service(l2cap_psm);
484     }
485 #endif
486     if (rfcomm_registered){
487         rfcomm_unregister_service(rfcomm_channel);
488     }
489     return status;
490 }
491 
492 uint8_t goep_server_accept_connection(uint16_t goep_cid){
493     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
494     if (connection == NULL){
495         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
496     }
497     if (connection->state != GOEP_SERVER_W4_ACCEPT_REJECT){
498         return ERROR_CODE_COMMAND_DISALLOWED;
499     }
500     connection->state = GOEP_SERVER_W4_CONNECTED;
501 #ifdef ENABLE_GOEP_L2CAP
502     if (connection->type == GOEP_CONNECTION_L2CAP){
503         return l2cap_ertm_accept_connection(connection->bearer_cid, &ertm_config, connection->ertm_buffer, GOEP_SERVER_ERTM_BUFFER);
504     }
505 #endif
506     return rfcomm_accept_connection(connection->bearer_cid);
507 }
508 
509 uint8_t goep_server_decline_connection(uint16_t goep_cid){
510     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
511     if (connection == NULL){
512         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
513     }
514     connection->state = GOEP_SERVER_W4_CONNECTED;
515     if (connection->state != GOEP_SERVER_W4_ACCEPT_REJECT){
516         return ERROR_CODE_COMMAND_DISALLOWED;
517     }
518 #ifdef ENABLE_GOEP_L2CAP
519     if (connection->type == GOEP_CONNECTION_L2CAP){
520         l2cap_decline_connection(connection->bearer_cid);
521         return ERROR_CODE_SUCCESS;
522     }
523 #endif
524     return rfcomm_decline_connection(connection->bearer_cid);
525 }
526 
527 uint8_t goep_server_request_can_send_now(uint16_t goep_cid){
528     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
529     if (connection == NULL){
530         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
531     }
532 
533     btstack_assert(connection->state == GOEP_SERVER_CONNECTED);
534 
535     switch (connection->type){
536         case GOEP_CONNECTION_RFCOMM:
537             rfcomm_request_can_send_now_event(connection->bearer_cid);
538             break;
539 #ifdef ENABLE_GOEP_L2CAP
540         case GOEP_CONNECTION_L2CAP:
541             l2cap_request_can_send_now_event(connection->bearer_cid);
542             break;
543 #endif
544         default:
545             btstack_unreachable();
546             break;
547     }
548     return ERROR_CODE_SUCCESS;
549 }
550 
551 static uint8_t * goep_server_get_outgoing_buffer(goep_server_connection_t * connection){
552     switch (connection->type){
553 #ifdef ENABLE_GOEP_L2CAP
554         case GOEP_CONNECTION_L2CAP:
555             return goep_server_l2cap_packet_buffer;
556 #endif
557         case GOEP_CONNECTION_RFCOMM:
558             return rfcomm_get_outgoing_buffer();
559         default:
560             btstack_unreachable();
561             return NULL;
562     }
563 }
564 
565 static uint16_t goep_server_get_outgoing_buffer_len(goep_server_connection_t * connection){
566     return connection->bearer_mtu;
567 }
568 
569 static void goep_server_packet_init(goep_server_connection_t * connection){
570     btstack_assert(connection->state == GOEP_SERVER_CONNECTED);
571     switch (connection->type){
572 #ifdef ENABLE_GOEP_L2CAP
573         case GOEP_CONNECTION_L2CAP:
574             break;
575 #endif
576         case GOEP_CONNECTION_RFCOMM:
577             rfcomm_reserve_packet_buffer();
578             break;
579         default:
580             btstack_unreachable();
581             break;
582     }
583     connection->state = GOEP_SERVER_OUTGOING_BUFFER_RESERVED;
584 }
585 
586 uint8_t goep_server_response_create_connect(uint16_t goep_cid, uint8_t obex_version_number, uint8_t flags, uint16_t maximum_obex_packet_length){
587     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
588     if (connection == NULL) {
589         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
590     }
591 
592     goep_server_packet_init(connection);
593 
594     // workaround: limit OBEX packet len to L2CAP/RFCOMM MTU
595     maximum_obex_packet_length = btstack_min(maximum_obex_packet_length, connection->bearer_mtu);
596 
597     uint8_t * buffer = goep_server_get_outgoing_buffer(connection);
598     uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
599     return obex_message_builder_response_create_connect(buffer, buffer_len, obex_version_number, flags, maximum_obex_packet_length, (uint32_t) goep_cid);
600 }
601 
602 uint8_t goep_server_response_create_general(uint16_t goep_cid){
603     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
604     if (connection == NULL) {
605         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
606     }
607     goep_server_packet_init(connection);
608     uint8_t * buffer = goep_server_get_outgoing_buffer(connection);
609     uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
610     return obex_message_builder_response_create_general(buffer, buffer_len, OBEX_RESP_SUCCESS);
611 }
612 
613 uint16_t goep_server_response_get_max_message_size(uint16_t goep_cid){
614     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
615     if (connection == NULL) {
616         return 0;
617     }
618     return goep_server_get_outgoing_buffer_len(connection);
619 }
620 
621 uint8_t goep_server_header_add_end_of_body(uint16_t goep_cid, const uint8_t * end_of_body, uint16_t length){
622     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
623     if (connection == NULL) {
624         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
625     }
626 
627     uint8_t * buffer = goep_server_get_outgoing_buffer(connection);
628     uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
629     return obex_message_builder_body_add_static(buffer, buffer_len, end_of_body, length);
630 }
631 
632 uint8_t goep_server_header_add_who(uint16_t goep_cid, const uint8_t * target){
633     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
634     if (connection == NULL) {
635         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
636     }
637 
638     uint8_t * buffer = goep_server_get_outgoing_buffer(connection);
639     uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
640     return obex_message_builder_header_add_who(buffer, buffer_len, target);
641 }
642 
643 uint8_t goep_server_header_add_srm_enable(uint16_t goep_cid){
644     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
645     if (connection == NULL) {
646         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
647     }
648 
649     uint8_t * buffer = goep_server_get_outgoing_buffer(connection);
650     uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
651     return obex_message_builder_header_add_srm_enable(buffer, buffer_len);
652 }
653 
654 uint8_t goep_server_header_add_srm_enable_wait(uint16_t goep_cid) {
655     goep_server_connection_t* connection = goep_server_get_connection_for_goep_cid(goep_cid);
656     if (connection == NULL) {
657         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
658     }
659 
660     uint8_t* buffer = goep_server_get_outgoing_buffer(connection);
661     uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
662     return obex_message_builder_header_add_srm_enable(buffer, buffer_len)
663         || obex_message_builder_header_add_srmp_wait(buffer, buffer_len);
664 }
665 
666 uint8_t goep_server_header_add_name(uint16_t goep_cid, const char* name) {
667 
668     if (name == NULL) {
669         return OBEX_UNKNOWN_ERROR;
670     }
671 
672     goep_server_connection_t* connection = goep_server_get_connection_for_goep_cid(goep_cid);
673     if (connection == NULL) {
674         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
675     }
676 
677     uint8_t* buffer = goep_server_get_outgoing_buffer(connection);
678     uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
679     return obex_message_builder_header_add_name(buffer, buffer_len, name);
680 }
681 
682 uint8_t goep_server_header_add_type(uint16_t goep_cid, const char* type) {
683 
684     if (type == NULL) {
685         return OBEX_UNKNOWN_ERROR;
686     }
687 
688     goep_server_connection_t* connection = goep_server_get_connection_for_goep_cid(goep_cid);
689     if (connection == NULL) {
690         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
691     }
692 
693     uint8_t* buffer = goep_server_get_outgoing_buffer(connection);
694     uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
695     return obex_message_builder_header_add_type(buffer, buffer_len, type);
696 }
697 
698 uint8_t goep_server_header_add_application_parameters(uint16_t goep_cid, const uint8_t * data, uint16_t length){
699     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
700     if (connection == NULL) {
701         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
702     }
703 
704     uint8_t * buffer = goep_server_get_outgoing_buffer(connection);
705     uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
706     return obex_message_builder_header_add_application_parameters(buffer, buffer_len, data, length);
707 }
708 
709 uint8_t goep_server_execute(uint16_t goep_cid, uint8_t response_code){
710     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
711     if (connection == NULL) {
712         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
713     }
714 
715     btstack_assert(connection->state == GOEP_SERVER_OUTGOING_BUFFER_RESERVED);
716 
717     connection->state = GOEP_SERVER_CONNECTED;
718 
719     uint8_t * buffer = goep_server_get_outgoing_buffer(connection);
720     // set response code
721     buffer[0] = response_code;
722     uint16_t pos = big_endian_read_16(buffer, 1);
723     switch (connection->type) {
724 #ifdef ENABLE_GOEP_L2CAP
725         case GOEP_CONNECTION_L2CAP:
726             return l2cap_send(connection->bearer_cid, buffer, pos);
727             break;
728 #endif
729         case GOEP_CONNECTION_RFCOMM:
730             return rfcomm_send_prepared(connection->bearer_cid, pos);
731         default:
732             btstack_unreachable();
733             return ERROR_CODE_SUCCESS;
734     }
735 }
736 
737 uint8_t goep_server_disconnect(uint16_t goep_cid){
738     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
739     if (connection == NULL) {
740         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
741     }
742 
743     if (connection->state < GOEP_SERVER_CONNECTED){
744         return ERROR_CODE_COMMAND_DISALLOWED;
745     }
746 
747     switch (connection->type) {
748 #ifdef ENABLE_GOEP_L2CAP
749         case GOEP_CONNECTION_L2CAP:
750             return l2cap_disconnect(connection->bearer_cid);
751 #endif
752         case GOEP_CONNECTION_RFCOMM:
753             return rfcomm_disconnect(connection->bearer_cid);
754         default:
755             btstack_unreachable();
756             break;
757     }
758     return ERROR_CODE_SUCCESS;
759 }
760 
761 void goep_server_deinit(void){
762     goep_server_cid_counter = 0;
763     goep_server_services = NULL;
764 }
765