xref: /btstack/src/classic/goep_server.c (revision ce6f85e79d1d141c1b45dfa16b2671762457cbb4)
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     2,
67     2,
68     1,      // 16-bit FCS
69 };
70 
71 static uint8_t goep_server_l2cap_packet_buffer[1000];
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     memcpy(&event[pos], bd_addr, 6);
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     memcpy(&event[pos], bd_addr, 6);
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 #endif
435 
436     // alloc structure
437     service = btstack_memory_goep_server_service_get();
438     if (service == NULL) {
439         return BTSTACK_MEMORY_ALLOC_FAILED;
440     }
441 
442     // fill in
443     service->callback = callback;
444     service->rfcomm_channel = rfcomm_channel;
445     service->l2cap_psm = l2cap_psm;
446 
447     uint8_t status = ERROR_CODE_SUCCESS;
448     bool rfcomm_registered = false;
449 
450 #ifdef ENABLE_GOEP_L2CAP
451     bool l2cap_registered = false;
452     // register with L2CAP
453     if (l2cap_psm != 0){
454         status = l2cap_register_service(goep_server_packet_handler_l2cap, l2cap_psm, l2cap_mtu, security_level);
455         if (status == ERROR_CODE_SUCCESS){
456             l2cap_registered = true;
457         }
458     }
459 #endif
460 
461     // register with RFCOMM
462     if (status == ERROR_CODE_SUCCESS){
463         status = rfcomm_register_service(goep_server_packet_handler_rfcomm, rfcomm_channel, rfcomm_max_frame_size);
464         if (status == ERROR_CODE_SUCCESS){
465             rfcomm_registered = true;
466         }
467     }
468 
469     // add service on success
470     if (status == ERROR_CODE_SUCCESS){
471         btstack_linked_list_add(&goep_server_services, (btstack_linked_item_t *) service);
472         return ERROR_CODE_SUCCESS;
473     }
474 
475     // unrestore otherwise
476     btstack_memory_goep_server_service_free(service);
477 #ifdef ENABLE_GOEP_L2CAP
478     if (l2cap_registered){
479         l2cap_unregister_service(l2cap_psm);
480     }
481 #endif
482     if (rfcomm_registered){
483         rfcomm_unregister_service(rfcomm_channel);
484     }
485     return status;
486 }
487 
488 uint8_t goep_server_accept_connection(uint16_t goep_cid){
489     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
490     if (connection == NULL){
491         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
492     }
493     if (connection->state != GOEP_SERVER_W4_ACCEPT_REJECT){
494         return ERROR_CODE_COMMAND_DISALLOWED;
495     }
496     connection->state = GOEP_SERVER_W4_CONNECTED;
497 #ifdef ENABLE_GOEP_L2CAP
498     if (connection->type == GOEP_CONNECTION_L2CAP){
499         return l2cap_ertm_accept_connection(connection->bearer_cid, &ertm_config, connection->ertm_buffer, GOEP_SERVER_ERTM_BUFFER);
500     }
501 #endif
502     return rfcomm_accept_connection(connection->bearer_cid);
503 }
504 
505 uint8_t goep_server_decline_connection(uint16_t goep_cid){
506     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
507     if (connection == NULL){
508         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
509     }
510     connection->state = GOEP_SERVER_W4_CONNECTED;
511     if (connection->state != GOEP_SERVER_W4_ACCEPT_REJECT){
512         return ERROR_CODE_COMMAND_DISALLOWED;
513     }
514 #ifdef ENABLE_GOEP_L2CAP
515     if (connection->type == GOEP_CONNECTION_L2CAP){
516         l2cap_decline_connection(connection->bearer_cid);
517         return ERROR_CODE_SUCCESS;
518     }
519 #endif
520     return rfcomm_decline_connection(connection->bearer_cid);
521 }
522 
523 uint8_t goep_server_request_can_send_now(uint16_t goep_cid){
524     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
525     if (connection == NULL){
526         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
527     }
528 
529     btstack_assert(connection->state == GOEP_SERVER_CONNECTED);
530 
531     switch (connection->type){
532         case GOEP_CONNECTION_RFCOMM:
533             rfcomm_request_can_send_now_event(connection->bearer_cid);
534             break;
535 #ifdef ENABLE_GOEP_L2CAP
536         case GOEP_CONNECTION_L2CAP:
537             l2cap_request_can_send_now_event(connection->bearer_cid);
538             break;
539 #endif
540         default:
541             btstack_unreachable();
542             break;
543     }
544     return ERROR_CODE_SUCCESS;
545 }
546 
547 static uint8_t * goep_server_get_outgoing_buffer(goep_server_connection_t * connection){
548     switch (connection->type){
549 #ifdef ENABLE_GOEP_L2CAP
550         case GOEP_CONNECTION_L2CAP:
551             return goep_server_l2cap_packet_buffer;
552 #endif
553         case GOEP_CONNECTION_RFCOMM:
554             return rfcomm_get_outgoing_buffer();
555         default:
556             btstack_unreachable();
557             return NULL;
558     }
559 }
560 
561 static uint16_t goep_server_get_outgoing_buffer_len(goep_server_connection_t * connection){
562     return connection->bearer_mtu;
563 }
564 
565 static void goep_server_packet_init(goep_server_connection_t * connection){
566     btstack_assert(connection->state == GOEP_SERVER_CONNECTED);
567     switch (connection->type){
568 #ifdef ENABLE_GOEP_L2CAP
569         case GOEP_CONNECTION_L2CAP:
570             break;
571 #endif
572         case GOEP_CONNECTION_RFCOMM:
573             rfcomm_reserve_packet_buffer();
574             break;
575         default:
576             btstack_unreachable();
577             break;
578     }
579     connection->state = GOEP_SERVER_OUTGOING_BUFFER_RESERVED;
580 }
581 
582 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){
583     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
584     if (connection == NULL) {
585         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
586     }
587 
588     goep_server_packet_init(connection);
589 
590     // workaround: limit OBEX packet len to L2CAP/RFCOMM MTU
591     maximum_obex_packet_length = btstack_min(maximum_obex_packet_length, connection->bearer_mtu);
592 
593     uint8_t * buffer = goep_server_get_outgoing_buffer(connection);
594     uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
595     return obex_message_builder_response_create_connect(buffer, buffer_len, obex_version_number, flags, maximum_obex_packet_length, (uint32_t) goep_cid);
596 }
597 
598 uint8_t goep_server_response_create_general(uint16_t goep_cid){
599     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
600     if (connection == NULL) {
601         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
602     }
603     goep_server_packet_init(connection);
604     uint8_t * buffer = goep_server_get_outgoing_buffer(connection);
605     uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
606     return obex_message_builder_response_create_general(buffer, buffer_len, OBEX_RESP_SUCCESS);
607 }
608 
609 uint16_t goep_server_response_get_max_message_size(uint16_t goep_cid){
610     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
611     if (connection == NULL) {
612         return 0;
613     }
614     return goep_server_get_outgoing_buffer_len(connection);
615 }
616 
617 uint8_t goep_server_header_add_end_of_body(uint16_t goep_cid, const uint8_t * end_of_body, uint16_t length){
618     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
619     if (connection == NULL) {
620         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
621     }
622 
623     uint8_t * buffer = goep_server_get_outgoing_buffer(connection);
624     uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
625     return obex_message_builder_body_add_static(buffer, buffer_len, end_of_body, length);
626 }
627 
628 uint8_t goep_server_header_add_who(uint16_t goep_cid, const uint8_t * target){
629     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
630     if (connection == NULL) {
631         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
632     }
633 
634     uint8_t * buffer = goep_server_get_outgoing_buffer(connection);
635     uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
636     return obex_message_builder_header_add_who(buffer, buffer_len, target);
637 }
638 
639 uint8_t goep_server_header_add_srm_enable(uint16_t goep_cid){
640     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
641     if (connection == NULL) {
642         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
643     }
644 
645     uint8_t * buffer = goep_server_get_outgoing_buffer(connection);
646     uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
647     return obex_message_builder_header_add_srm_enable(buffer, buffer_len);
648 }
649 
650 uint8_t goep_server_header_add_application_parameters(uint16_t goep_cid, const uint8_t * data, uint16_t length){
651     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
652     if (connection == NULL) {
653         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
654     }
655 
656     uint8_t * buffer = goep_server_get_outgoing_buffer(connection);
657     uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
658     return obex_message_builder_header_add_application_parameters(buffer, buffer_len, data, length);
659 }
660 
661 uint8_t goep_server_execute(uint16_t goep_cid, uint8_t response_code){
662     goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
663     if (connection == NULL) {
664         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
665     }
666 
667     btstack_assert(connection->state == GOEP_SERVER_OUTGOING_BUFFER_RESERVED);
668 
669     connection->state = GOEP_SERVER_CONNECTED;
670 
671     uint8_t * buffer = goep_server_get_outgoing_buffer(connection);
672     // set response code
673     buffer[0] = response_code;
674     uint16_t pos = big_endian_read_16(buffer, 1);
675     switch (connection->type) {
676 #ifdef ENABLE_GOEP_L2CAP
677         case GOEP_CONNECTION_L2CAP:
678             return l2cap_send(connection->bearer_cid, buffer, pos);
679             break;
680 #endif
681         case GOEP_CONNECTION_RFCOMM:
682             return rfcomm_send_prepared(connection->bearer_cid, pos);
683             break;
684         default:
685             btstack_unreachable();
686             return ERROR_CODE_SUCCESS;
687     }
688 }
689 
690 void goep_server_deinit(void){
691     goep_server_cid_counter = 0;
692     goep_server_services = NULL;
693 }
694