1/*
2 * Copyright 2008, Oliver Ruiz Dorantes. All rights reserved.
3 * Copyright 2024, Haiku, Inc. All rights reserved.
4 * Distributed under the terms of the MIT License.
5 */
6#include "L2capEndpoint.h"
7
8#include <stdio.h>
9#include <string.h>
10
11#include <NetBufferUtilities.h>
12
13#include <btDebug.h>
14#include "L2capEndpointManager.h"
15#include "l2cap_address.h"
16#include "l2cap_signal.h"
17
18
19static l2cap_qos sDefaultQOS = {
20	.flags = 0x0,
21	.service_type = 1,
22	.token_rate = 0xffffffff, /* maximum */
23	.token_bucket_size = 0xffffffff, /* maximum */
24	.peak_bandwidth = 0x00000000, /* maximum */
25	.access_latency = 0xffffffff, /* don't care */
26	.delay_variation = 0xffffffff /* don't care */
27};
28
29
30static inline bigtime_t
31absolute_timeout(bigtime_t timeout)
32{
33	if (timeout == 0 || timeout == B_INFINITE_TIMEOUT)
34		return timeout;
35
36	return timeout + system_time();
37}
38
39
40static inline status_t
41posix_error(status_t error)
42{
43	if (error == B_TIMED_OUT)
44		return B_WOULD_BLOCK;
45
46	return error;
47}
48
49
50// #pragma mark - endpoint
51
52
53L2capEndpoint::L2capEndpoint(net_socket* socket)
54	:
55	ProtocolSocket(socket),
56	fAcceptSemaphore(-1),
57	fState(CLOSED),
58	fConnection(NULL),
59	fChannelID(L2CAP_NULL_CID),
60	fDestinationChannelID(L2CAP_NULL_CID)
61{
62	CALLED();
63
64	mutex_init(&fLock, "l2cap endpoint");
65	fCommandWait.Init(this, "l2cap endpoint command");
66
67	// Set MTU and flow control settings to defaults
68	fChannelConfig.incoming_mtu = L2CAP_MTU_DEFAULT;
69	memcpy(&fChannelConfig.incoming_flow, &sDefaultQOS, sizeof(l2cap_qos));
70
71	fChannelConfig.outgoing_mtu = L2CAP_MTU_DEFAULT;
72	memcpy(&fChannelConfig.outgoing_flow, &sDefaultQOS, sizeof(l2cap_qos));
73
74	fChannelConfig.flush_timeout = L2CAP_FLUSH_TIMEOUT_DEFAULT;
75	fChannelConfig.link_timeout  = L2CAP_LINK_TIMEOUT_DEFAULT;
76
77	fConfigState = {};
78
79	gStackModule->init_fifo(&fReceiveQueue, "l2cap recv", L2CAP_MTU_MAXIMUM);
80	gStackModule->init_fifo(&fSendQueue, "l2cap send", L2CAP_MTU_MAXIMUM);
81	gStackModule->init_timer(&fSendTimer, L2capEndpoint::_SendTimer, this);
82}
83
84
85L2capEndpoint::~L2capEndpoint()
86{
87	CALLED();
88
89	mutex_lock(&fLock);
90	mutex_destroy(&fLock);
91
92	ASSERT(fState == CLOSED);
93
94	fCommandWait.NotifyAll(B_ERROR);
95
96	gStackModule->uninit_fifo(&fReceiveQueue);
97	gStackModule->uninit_fifo(&fSendQueue);
98	gStackModule->wait_for_timer(&fSendTimer);
99}
100
101
102status_t
103L2capEndpoint::_WaitForStateChange(bigtime_t absoluteTimeout)
104{
105	channel_status state = fState;
106	while (fState == state) {
107		status_t status = fCommandWait.Wait(&fLock,
108			B_ABSOLUTE_TIMEOUT | B_CAN_INTERRUPT, absoluteTimeout);
109		if (status != B_OK)
110			return posix_error(status);
111	}
112
113	return B_OK;
114}
115
116
117status_t
118L2capEndpoint::Open()
119{
120	CALLED();
121	return ProtocolSocket::Open();
122}
123
124
125status_t
126L2capEndpoint::Shutdown()
127{
128	CALLED();
129	MutexLocker locker(fLock);
130
131	if (fState == CLOSED) {
132		// Nothing to do.
133		return B_OK;
134	}
135	if (fState == LISTEN) {
136		delete_sem(fAcceptSemaphore);
137		fAcceptSemaphore = -1;
138		gSocketModule->set_max_backlog(socket, 0);
139		fState = BOUND;
140		return B_OK;
141	}
142
143	status_t status;
144	bigtime_t timeout = absolute_timeout(socket->receive.timeout);
145	if (gStackModule->is_restarted_syscall())
146		timeout = gStackModule->restore_syscall_restart_timeout();
147	else
148		gStackModule->store_syscall_restart_timeout(timeout);
149
150	// FIXME: If we are currently waiting for a connection or configuration,
151	// we need to wait for that command to return (and free its ident on timeout.)
152
153	while (fState > OPEN) {
154		status = _WaitForStateChange(timeout);
155		if (status != B_OK)
156			return status;
157	}
158	if (fState == CLOSED)
159		return B_OK;
160
161	uint8 ident = btCoreData->allocate_command_ident(fConnection, this);
162	if (ident == L2CAP_NULL_IDENT)
163		return ENOBUFS;
164
165	status = send_l2cap_disconnection_req(fConnection, ident,
166		fDestinationChannelID, fChannelID);
167	if (status != B_OK)
168		return status;
169
170	fState = WAIT_FOR_DISCONNECTION_RSP;
171
172	while (fState != CLOSED) {
173		status = _WaitForStateChange(timeout);
174		if (status != B_OK)
175			return status;
176	}
177
178	return B_OK;
179}
180
181
182status_t
183L2capEndpoint::Close()
184{
185	return Shutdown();
186}
187
188
189status_t
190L2capEndpoint::Free()
191{
192	CALLED();
193
194	return B_OK;
195}
196
197
198status_t
199L2capEndpoint::Bind(const struct sockaddr* _address)
200{
201	const sockaddr_l2cap* address
202		= reinterpret_cast<const sockaddr_l2cap*>(_address);
203	if (AddressModule()->is_empty_address(_address, true))
204		return B_OK; // We don't need to bind to empty.
205	if (!AddressModule()->is_same_family(_address))
206		return EAFNOSUPPORT;
207	if (address->l2cap_len != sizeof(struct sockaddr_l2cap))
208		return EAFNOSUPPORT;
209
210	CALLED();
211	MutexLocker _(fLock);
212
213	if (fState != CLOSED)
214		return EISCONN;
215
216	status_t status = gL2capEndpointManager.Bind(this, *address);
217	if (status != B_OK)
218		return status;
219
220	fState = BOUND;
221	return B_OK;
222}
223
224
225status_t
226L2capEndpoint::Unbind()
227{
228	CALLED();
229	MutexLocker _(fLock);
230
231	if (LocalAddress().IsEmpty(true))
232		return EINVAL;
233
234	status_t status = gL2capEndpointManager.Unbind(this);
235	if (status != B_OK)
236		return status;
237
238	if (fState == BOUND)
239		fState = CLOSED;
240	return B_OK;
241}
242
243
244status_t
245L2capEndpoint::Listen(int backlog)
246{
247	CALLED();
248	MutexLocker _(fLock);
249
250	if (fState != BOUND)
251		return B_BAD_VALUE;
252
253	fAcceptSemaphore = create_sem(0, "l2cap accept");
254	if (fAcceptSemaphore < B_OK) {
255		ERROR("%s: Semaphore could not be created\n", __func__);
256		return ENOBUFS;
257	}
258
259	gSocketModule->set_max_backlog(socket, backlog);
260
261	fState = LISTEN;
262	return B_OK;
263}
264
265
266status_t
267L2capEndpoint::Connect(const struct sockaddr* _address)
268{
269	const sockaddr_l2cap* address
270		= reinterpret_cast<const sockaddr_l2cap*>(_address);
271	if (!AddressModule()->is_same_family(_address))
272		return EAFNOSUPPORT;
273	if (address->l2cap_len != sizeof(struct sockaddr_l2cap))
274		return EAFNOSUPPORT;
275
276	TRACE("l2cap: connect(\"%s\")\n",
277		ConstSocketAddress(&gL2capAddressModule, _address).AsString().Data());
278	MutexLocker _(fLock);
279
280	status_t status;
281	bigtime_t timeout = absolute_timeout(socket->send.timeout);
282	if (gStackModule->is_restarted_syscall()) {
283		timeout = gStackModule->restore_syscall_restart_timeout();
284
285		while (fState != CLOSED && fState != OPEN) {
286			status = _WaitForStateChange(timeout);
287			if (status != B_OK)
288				return status;
289		}
290		return (fState == OPEN) ? B_OK : ECONNREFUSED;
291	} else {
292		gStackModule->store_syscall_restart_timeout(timeout);
293	}
294
295	if (fState == LISTEN)
296		return EINVAL;
297	if (fState == OPEN)
298		return EISCONN;
299	if (fState != CLOSED)
300		return EALREADY;
301
302	// Set up route.
303	hci_id hid = btCoreData->RouteConnection(address->l2cap_bdaddr);
304	if (hid <= 0)
305		return ENETUNREACH;
306
307	TRACE("l2cap: %" B_PRId32 " for route %s\n", hid,
308		bdaddrUtils::ToString(address->l2cap_bdaddr).String());
309
310	fConnection = btCoreData->ConnectionByDestination(
311		address->l2cap_bdaddr, hid);
312	if (fConnection == NULL)
313		return EHOSTUNREACH;
314
315	memcpy(&socket->peer, _address, sizeof(struct sockaddr_l2cap));
316
317	status = gL2capEndpointManager.BindToChannel(this);
318	if (status != B_OK)
319		return status;
320
321	fConfigState = {};
322
323	uint8 ident = btCoreData->allocate_command_ident(fConnection, this);
324	if (ident == L2CAP_NULL_IDENT)
325		return ENOBUFS;
326
327	status = send_l2cap_connection_req(fConnection, ident,
328		address->l2cap_psm, fChannelID);
329	if (status != B_OK)
330		return status;
331
332	fState = WAIT_FOR_CONNECTION_RSP;
333
334	while (fState != CLOSED && fState != OPEN) {
335		status = _WaitForStateChange(timeout);
336		if (status != B_OK)
337			return status;
338	}
339	return (fState == OPEN) ? B_OK : ECONNREFUSED;
340}
341
342
343status_t
344L2capEndpoint::Accept(net_socket** _acceptedSocket)
345{
346	CALLED();
347	MutexLocker locker(fLock);
348
349	status_t status;
350	bigtime_t timeout = absolute_timeout(socket->receive.timeout);
351	if (gStackModule->is_restarted_syscall())
352		timeout = gStackModule->restore_syscall_restart_timeout();
353	else
354		gStackModule->store_syscall_restart_timeout(timeout);
355
356	do {
357		locker.Unlock();
358
359		status = acquire_sem_etc(fAcceptSemaphore, 1, B_ABSOLUTE_TIMEOUT
360			| B_CAN_INTERRUPT, timeout);
361		if (status != B_OK) {
362			if (status == B_TIMED_OUT && socket->receive.timeout == 0)
363				return B_WOULD_BLOCK;
364
365			return status;
366		}
367
368		locker.Lock();
369		status = gSocketModule->dequeue_connected(socket, _acceptedSocket);
370	} while (status != B_OK);
371
372	return status;
373}
374
375
376ssize_t
377L2capEndpoint::ReadData(size_t numBytes, uint32 flags, net_buffer** _buffer)
378{
379	CALLED();
380	MutexLocker locker(fLock);
381
382	*_buffer = NULL;
383
384	bigtime_t timeout = 0;
385	if ((flags & MSG_DONTWAIT) == 0) {
386		timeout = absolute_timeout(socket->receive.timeout);
387		if (gStackModule->is_restarted_syscall())
388			timeout = gStackModule->restore_syscall_restart_timeout();
389		else
390			gStackModule->store_syscall_restart_timeout(timeout);
391	}
392
393	if (fState == CLOSED)
394		flags |= MSG_DONTWAIT;
395
396	return gStackModule->fifo_dequeue_buffer(&fReceiveQueue, flags, timeout, _buffer);
397}
398
399
400ssize_t
401L2capEndpoint::SendData(net_buffer* buffer)
402{
403	CALLED();
404	MutexLocker locker(fLock);
405
406	if (buffer == NULL)
407		return ENOBUFS;
408
409	if (fState != OPEN)
410		return ENOTCONN;
411
412	ssize_t sent = 0;
413	while (buffer != NULL) {
414		net_buffer* current = buffer;
415		buffer = NULL;
416		if (current->size > fChannelConfig.outgoing_mtu) {
417			// Break up into MTU-sized chunks.
418			buffer = gBufferModule->split(current, fChannelConfig.outgoing_mtu);
419			if (buffer == NULL) {
420				if (sent > 0) {
421					gBufferModule->free(current);
422					return sent;
423				}
424				return ENOMEM;
425			}
426		}
427
428		const size_t bufferSize = current->size;
429		status_t status = gStackModule->fifo_enqueue_buffer(&fSendQueue, current);
430		if (status != B_OK) {
431			gBufferModule->free(current);
432			return sent;
433		}
434
435		sent += bufferSize;
436	}
437
438	if (!gStackModule->is_timer_active(&fSendTimer))
439		gStackModule->set_timer(&fSendTimer, 0);
440
441	return sent;
442}
443
444
445status_t
446L2capEndpoint::ReceiveData(net_buffer* buffer)
447{
448	// FIXME: Check address specified in net_buffer!
449	return gStackModule->fifo_enqueue_buffer(&fReceiveQueue, buffer);
450}
451
452
453/*static*/ void
454L2capEndpoint::_SendTimer(net_timer* timer, void* _endpoint)
455{
456	L2capEndpoint* endpoint = (L2capEndpoint*)_endpoint;
457
458	MutexLocker locker(endpoint->fLock);
459	if (!locker.IsLocked() || gStackModule->is_timer_active(timer))
460		return;
461
462	endpoint->_SendQueued();
463}
464
465
466void
467L2capEndpoint::_SendQueued()
468{
469	CALLED();
470	ASSERT_LOCKED_MUTEX(&fLock);
471
472	if (fState != OPEN)
473		return;
474
475	net_buffer* buffer;
476	while (gStackModule->fifo_dequeue_buffer(&fSendQueue, MSG_DONTWAIT, 0, &buffer) >= 0) {
477		NetBufferPrepend<l2cap_basic_header> header(buffer);
478		if (header.Status() != B_OK) {
479			ERROR("%s: header could not be prepended!\n", __func__);
480			gBufferModule->free(buffer);
481			continue;
482		}
483
484		header->length = B_HOST_TO_LENDIAN_INT16(buffer->size - sizeof(l2cap_basic_header));
485		header->dcid = B_HOST_TO_LENDIAN_INT16(fDestinationChannelID);
486
487		buffer->type = fConnection->handle;
488		btDevices->PostACL(fConnection->ndevice->index, buffer);
489	}
490}
491
492
493ssize_t
494L2capEndpoint::Sendable()
495{
496	CALLED();
497	MutexLocker locker(fLock);
498
499	if (fState != OPEN) {
500		if (_IsEstablishing())
501			return 0;
502		return EPIPE;
503	}
504
505	MutexLocker fifoLocker(fSendQueue.lock);
506	return (fSendQueue.max_bytes - fSendQueue.current_bytes);
507}
508
509
510ssize_t
511L2capEndpoint::Receivable()
512{
513	CALLED();
514	MutexLocker locker(fLock);
515
516	MutexLocker fifoLocker(fReceiveQueue.lock);
517	return fReceiveQueue.current_bytes;
518}
519
520
521void
522L2capEndpoint::_HandleCommandRejected(uint8 ident, uint16 reason,
523	const l2cap_command_reject_data& data)
524{
525	CALLED();
526	MutexLocker locker(fLock);
527
528	switch (fState) {
529		case WAIT_FOR_CONNECTION_RSP:
530			// Connection request was rejected. Reset state.
531			fState = CLOSED;
532			socket->error = ECONNREFUSED;
533		break;
534
535		case CONFIGURATION:
536			// TODO: Adjust and resend configuration request.
537		break;
538
539	default:
540		ERROR("l2cap: unknown command unexpectedly rejected (ident %d)\n", ident);
541		break;
542	}
543
544	fCommandWait.NotifyAll();
545}
546
547
548void
549L2capEndpoint::_HandleConnectionReq(HciConnection* connection,
550	uint8 ident, uint16 psm, uint16 scid)
551{
552	MutexLocker locker(fLock);
553	if (fState != LISTEN) {
554		send_l2cap_connection_rsp(connection, ident, 0, scid,
555			l2cap_connection_rsp::RESULT_PSM_NOT_SUPPORTED, 0);
556		return;
557	}
558	locker.Unlock();
559
560	net_socket* newSocket;
561	status_t status = gSocketModule->spawn_pending_socket(socket, &newSocket);
562	if (status != B_OK) {
563		ERROR("l2cap: could not spawn child for endpoint: %s\n", strerror(status));
564		send_l2cap_connection_rsp(connection, ident, 0, scid,
565			l2cap_connection_rsp::RESULT_NO_RESOURCES, 0);
566		return;
567	}
568
569	L2capEndpoint* endpoint = (L2capEndpoint*)newSocket->first_protocol;
570	MutexLocker newEndpointLocker(endpoint->fLock);
571
572	status = gL2capEndpointManager.BindToChannel(endpoint);
573	if (status != B_OK) {
574		ERROR("l2cap: could not allocate channel for endpoint: %s\n", strerror(status));
575		send_l2cap_connection_rsp(connection, ident, 0, scid,
576			l2cap_connection_rsp::RESULT_NO_RESOURCES, 0);
577		return;
578	}
579
580	endpoint->fAcceptSemaphore = fAcceptSemaphore;
581
582	endpoint->fConnection = connection;
583	endpoint->fState = CONFIGURATION;
584
585	endpoint->fDestinationChannelID = scid;
586
587	send_l2cap_connection_rsp(connection, ident, endpoint->fChannelID, scid,
588		l2cap_connection_rsp::RESULT_SUCCESS, 0);
589}
590
591
592void
593L2capEndpoint::_HandleConnectionRsp(uint8 ident, const l2cap_connection_rsp& response)
594{
595	CALLED();
596	MutexLocker locker(fLock);
597	fCommandWait.NotifyAll();
598
599	if (fState != WAIT_FOR_CONNECTION_RSP) {
600		ERROR("l2cap: unexpected connection response, scid=%d, state=%d\n",
601			response.scid, fState);
602		send_l2cap_command_reject(fConnection, ident,
603			l2cap_command_reject::REJECTED_INVALID_CID, 0, response.scid, response.dcid);
604		return;
605	}
606
607	if (fChannelID != response.scid) {
608		ERROR("l2cap: invalid connection response, mismatched SCIDs (%d, %d)\n",
609			fChannelID, response.scid);
610		send_l2cap_command_reject(fConnection, ident,
611			l2cap_command_reject::REJECTED_INVALID_CID, 0, response.scid, response.dcid);
612		return;
613	}
614
615	if (response.result == l2cap_connection_rsp::RESULT_PENDING) {
616		// The connection is still pending on the remote end.
617		// We will receive another CONNECTION_RSP later.
618
619		// TODO: Increase/reset timeout? (We don't have any timeouts presently.)
620		return;
621	} else if (response.result != l2cap_connection_rsp::RESULT_SUCCESS) {
622		// Some error response.
623		// TODO: Translate `result` if possible?
624		socket->error = ECONNREFUSED;
625
626		fState = CLOSED;
627		fCommandWait.NotifyAll();
628	}
629
630	// Success: channel is now open for configuration.
631	fState = CONFIGURATION;
632	fDestinationChannelID = response.dcid;
633
634	_SendChannelConfig();
635}
636
637
638void
639L2capEndpoint::_SendChannelConfig()
640{
641	uint16* mtu = NULL;
642	if (fChannelConfig.incoming_mtu != L2CAP_MTU_DEFAULT)
643		mtu = &fChannelConfig.incoming_mtu;
644
645	uint16* flush_timeout = NULL;
646	if (fChannelConfig.flush_timeout != L2CAP_FLUSH_TIMEOUT_DEFAULT)
647		flush_timeout = &fChannelConfig.flush_timeout;
648
649	l2cap_qos* flow = NULL;
650	if (memcmp(&sDefaultQOS, &fChannelConfig.outgoing_flow,
651			sizeof(fChannelConfig.outgoing_flow)) != 0) {
652		flow = &fChannelConfig.outgoing_flow;
653	}
654
655	uint8 ident = btCoreData->allocate_command_ident(fConnection, this);
656	if (ident == L2CAP_NULL_IDENT) {
657		// TODO: Retry later?
658		return;
659	}
660
661	status_t status = send_l2cap_configuration_req(fConnection, ident,
662		fDestinationChannelID, 0, flush_timeout, mtu, flow);
663	if (status != B_OK) {
664		socket->error = status;
665		return;
666	}
667
668	fConfigState.out = ConfigState::SENT;
669}
670
671
672void
673L2capEndpoint::_HandleConfigurationReq(uint8 ident, uint16 flags,
674	uint16* mtu, uint16* flush_timeout, l2cap_qos* flow)
675{
676	CALLED();
677	MutexLocker locker(fLock);
678	fCommandWait.NotifyAll();
679
680	if (fState != CONFIGURATION && fState != OPEN) {
681		ERROR("l2cap: unexpected configuration req: invalid channel state (cid=%d, state=%d)\n",
682			fChannelID, fState);
683		send_l2cap_configuration_rsp(fConnection, ident, fChannelID, 0,
684			l2cap_configuration_rsp::RESULT_REJECTED, NULL);
685		return;
686	}
687
688	if (fState == OPEN) {
689		// Re-configuration.
690		fConfigState = {};
691		fState = CONFIGURATION;
692	}
693
694	// Process options.
695	// TODO: Validate parameters!
696	if (mtu != NULL && *mtu != fChannelConfig.outgoing_mtu)
697		fChannelConfig.outgoing_mtu = *mtu;
698	if (flush_timeout != NULL && *flush_timeout != fChannelConfig.flush_timeout)
699		fChannelConfig.flush_timeout = *flush_timeout;
700	if (flow != NULL)
701		fChannelConfig.incoming_flow = *flow;
702
703	send_l2cap_configuration_rsp(fConnection, ident, fChannelID, 0,
704		l2cap_configuration_rsp::RESULT_SUCCESS, NULL);
705
706	if ((flags & L2CAP_CFG_FLAG_CONTINUATION) != 0) {
707		// More options are coming, just keep waiting.
708		return;
709	}
710
711	// We now have all options.
712	fConfigState.in = ConfigState::DONE;
713
714	if (fConfigState.out < ConfigState::SENT)
715		_SendChannelConfig();
716	else if (fConfigState.out == ConfigState::DONE)
717		_MarkEstablished();
718}
719
720
721void
722L2capEndpoint::_HandleConfigurationRsp(uint8 ident, uint16 scid, uint16 flags,
723	uint16 result, uint16* mtu, uint16* flush_timeout, l2cap_qos* flow)
724{
725	CALLED();
726	MutexLocker locker(fLock);
727	fCommandWait.NotifyAll();
728
729	if (fState != CONFIGURATION) {
730		ERROR("l2cap: unexpected configuration rsp: invalid channel state (cid=%d, state=%d)\n",
731			fChannelID, fState);
732		send_l2cap_command_reject(fConnection, ident,
733			l2cap_command_reject::REJECTED_INVALID_CID, 0, scid, fChannelID);
734		return;
735	}
736	if (scid != fChannelID) {
737		ERROR("l2cap: unexpected configuration rsp: invalid source channel (cid=%d, scid=%d)\n",
738			fChannelID, scid);
739		send_l2cap_command_reject(fConnection, ident,
740			l2cap_command_reject::REJECTED_INVALID_CID, 0, scid, fChannelID);
741		return;
742	}
743
744	// TODO: Validate parameters!
745	if (result == l2cap_configuration_rsp::RESULT_PENDING) {
746		// We will receive another CONFIGURATION_RSP later.
747		return;
748	} else if (result == l2cap_configuration_rsp::RESULT_UNACCEPTABLE_PARAMS) {
749		// The acceptable parameters are specified in options.
750		if (mtu != NULL && *mtu != fChannelConfig.incoming_mtu)
751			fChannelConfig.incoming_mtu = *mtu;
752		if (flush_timeout != NULL && *flush_timeout != fChannelConfig.flush_timeout)
753			fChannelConfig.flush_timeout = *flush_timeout;
754	} else if (result == l2cap_configuration_rsp::RESULT_FLOW_SPEC_REJECTED) {
755		if (flow != NULL)
756			fChannelConfig.outgoing_flow = *flow;
757	} else if (result != l2cap_configuration_rsp::RESULT_SUCCESS) {
758		ERROR("l2cap: unhandled configuration response! (result=%d)\n",
759			result);
760		return;
761	}
762
763	if ((flags & L2CAP_CFG_FLAG_CONTINUATION) != 0) {
764		// More options are coming, just keep waiting.
765		return;
766	}
767
768	if (result != l2cap_configuration_rsp::RESULT_SUCCESS) {
769		// Resend configuration request to try again.
770		_SendChannelConfig();
771		return;
772	}
773
774	// We now have all options.
775	fConfigState.out = ConfigState::DONE;
776
777	if (fConfigState.in == ConfigState::DONE)
778		_MarkEstablished();
779}
780
781
782status_t
783L2capEndpoint::_MarkEstablished()
784{
785	CALLED();
786	ASSERT_LOCKED_MUTEX(&fLock);
787
788	fState = OPEN;
789	fCommandWait.NotifyAll();
790
791	status_t error = B_OK;
792	if (gSocketModule->has_parent(socket)) {
793		error = gSocketModule->set_connected(socket);
794		if (error == B_OK) {
795			release_sem(fAcceptSemaphore);
796			fAcceptSemaphore = -1;
797		} else {
798			ERROR("%s: could not set endpoint %p connected: %s\n", __func__, this,
799				strerror(error));
800		}
801	}
802
803	return error;
804}
805
806
807void
808L2capEndpoint::_HandleDisconnectionReq(uint8 ident, uint16 scid)
809{
810	CALLED();
811	MutexLocker locker(fLock);
812	fCommandWait.NotifyAll();
813
814	if (scid != fDestinationChannelID) {
815		ERROR("l2cap: unexpected disconnection req: invalid source channel (cid=%d, scid=%d)\n",
816			fChannelID, scid);
817		send_l2cap_command_reject(fConnection, ident,
818			l2cap_command_reject::REJECTED_INVALID_CID, 0, scid, fChannelID);
819		return;
820	}
821
822	if (fState != WAIT_FOR_DISCONNECTION_RSP)
823		fState = RECEIVED_DISCONNECTION_REQ;
824
825	// The dcid/scid are the same as in the REQ command.
826	status_t status = send_l2cap_disconnection_rsp(fConnection, ident, fChannelID, scid);
827	if (status != B_OK) {
828		// TODO?
829		return;
830	}
831
832	_MarkClosed();
833}
834
835
836void
837L2capEndpoint::_HandleDisconnectionRsp(uint8 ident, uint16 dcid, uint16 scid)
838{
839	CALLED();
840	MutexLocker locker(fLock);
841	fCommandWait.NotifyAll();
842
843	if (fState != WAIT_FOR_DISCONNECTION_RSP) {
844		ERROR("l2cap: unexpected disconnection rsp (cid=%d, scid=%d)\n",
845			fChannelID, scid);
846		send_l2cap_command_reject(fConnection, ident,
847			l2cap_command_reject::REJECTED_INVALID_CID, 0, scid, fChannelID);
848		return;
849	}
850
851	if (dcid != fDestinationChannelID && scid != fChannelID) {
852		ERROR("l2cap: unexpected disconnection rsp: mismatched CIDs (dcid=%d, scid=%d)\n",
853			dcid, scid);
854		return;
855	}
856
857	_MarkClosed();
858}
859
860
861void
862L2capEndpoint::_MarkClosed()
863{
864	CALLED();
865	ASSERT_LOCKED_MUTEX(&fLock);
866
867	fState = CLOSED;
868
869	gL2capEndpointManager.UnbindFromChannel(this);
870}
871