1/*
2 * Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5#include "L2capEndpoint.h"
6#include "l2cap_address.h"
7#include "l2cap_upper.h"
8#include "l2cap_lower.h"
9
10#include <stdio.h>
11#include <string.h>
12#include <sys/stat.h>
13
14#include <bluetooth/bdaddrUtils.h>
15#include <bluetooth/L2CAP/btL2CAP.h>
16
17#include <btDebug.h>
18
19
20static inline bigtime_t
21absolute_timeout(bigtime_t timeout)
22{
23	if (timeout == 0 || timeout == B_INFINITE_TIMEOUT)
24		return timeout;
25
26	// TODO: Make overflow safe!
27	return timeout + system_time();
28}
29
30
31L2capEndpoint::L2capEndpoint(net_socket* socket)
32	:
33	ProtocolSocket(socket),
34	fConfigurationSet(false),
35	fEstablishSemaphore(-1),
36	fPeerEndpoint(NULL),
37	fChannel(NULL)
38{
39	CALLED();
40
41	/* Set MTU and flow control settings to defaults */
42	fConfiguration.imtu = L2CAP_MTU_DEFAULT;
43	memcpy(&fConfiguration.iflow, &default_qos , sizeof(l2cap_flow_t) );
44
45	fConfiguration.omtu = L2CAP_MTU_DEFAULT;
46	memcpy(&fConfiguration.oflow, &default_qos , sizeof(l2cap_flow_t) );
47
48	fConfiguration.flush_timo = L2CAP_FLUSH_TIMO_DEFAULT;
49	fConfiguration.link_timo  = L2CAP_LINK_TIMO_DEFAULT;
50
51	// TODO: XXX not for listening endpoints, imtu should be known first
52	gStackModule->init_fifo(&fReceivingFifo, "l2cap recvfifo", L2CAP_MTU_DEFAULT);
53}
54
55
56L2capEndpoint::~L2capEndpoint()
57{
58	CALLED();
59
60	gStackModule->uninit_fifo(&fReceivingFifo);
61}
62
63
64status_t
65L2capEndpoint::Init()
66{
67	CALLED();
68
69	return B_OK;
70}
71
72
73void
74L2capEndpoint::Uninit()
75{
76	CALLED();
77
78}
79
80
81status_t
82L2capEndpoint::Open()
83{
84	CALLED();
85
86	status_t error = ProtocolSocket::Open();
87	if (error != B_OK)
88		return error;
89
90	return B_OK;
91}
92
93
94status_t
95L2capEndpoint::Close()
96{
97	CALLED();
98
99	if (fChannel == NULL) {
100		// TODO: Parent socket
101
102	} else {
103		// Child Socket
104		if (fState == CLOSED) {
105			// TODO: Clean needed stuff
106			return B_OK;
107		} else {
108			// Issue Disconnection request over the channel
109			MarkClosed();
110
111			bigtime_t timeout = absolute_timeout(300 * 1000 * 1000);
112
113			status_t error = l2cap_upper_dis_req(fChannel);
114
115			if (error != B_OK)
116				return error;
117
118			return acquire_sem_etc(fEstablishSemaphore, 1,
119				B_ABSOLUTE_TIMEOUT | B_CAN_INTERRUPT, timeout);
120		}
121	}
122
123	if (fEstablishSemaphore != -1) {
124		delete_sem(fEstablishSemaphore);
125	}
126
127	return B_OK;
128}
129
130
131status_t
132L2capEndpoint::Free()
133{
134	CALLED();
135
136	return B_OK;
137}
138
139
140status_t
141L2capEndpoint::Bind(const struct sockaddr* _address)
142{
143	const sockaddr_l2cap* address
144		= reinterpret_cast<const sockaddr_l2cap*>(_address);
145
146	if (_address == NULL)
147		return B_ERROR;
148
149	if (address->l2cap_family != AF_BLUETOOTH )
150		return EAFNOSUPPORT;
151
152	if (address->l2cap_len != sizeof(struct sockaddr_l2cap))
153		return EAFNOSUPPORT;
154
155	// TODO: Check if that PSM is already bound
156	// return EADDRINUSE;
157
158	// TODO: Check if the PSM is valid, check assigned numbers document for valid
159	// psm available to applications.
160	// All PSM values shall be ODD, that is, the least significant bit of the least
161	// significant octet must be ���1���. Also, all PSM values shall have the least
162	// significant bit of the most significant octet equal to ���0���. This allows
163	// the PSM field to be extended beyond 16 bits.
164	if ((address->l2cap_psm & 1) == 0)
165		return B_ERROR;
166
167	memcpy(&socket->address, _address, sizeof(struct sockaddr_l2cap));
168	socket->address.ss_len = sizeof(struct sockaddr_l2cap);
169
170	fState = BOUND;
171
172	return B_OK;
173}
174
175
176status_t
177L2capEndpoint::Unbind()
178{
179	CALLED();
180
181	return B_OK;
182}
183
184
185status_t
186L2capEndpoint::Listen(int backlog)
187{
188	CALLED();
189
190	if (fState != BOUND) {
191		ERROR("%s: Invalid State\n", __func__);
192		return B_BAD_VALUE;
193	}
194
195	fEstablishSemaphore = create_sem(0, "l2cap serv accept");
196	if (fEstablishSemaphore < B_OK) {
197		ERROR("%s: Semaphore could not be created\n", __func__);
198		return ENOBUFS;
199	}
200
201	gSocketModule->set_max_backlog(socket, backlog);
202
203	fState = LISTEN;
204
205	return B_OK;
206}
207
208
209status_t
210L2capEndpoint::Connect(const struct sockaddr* _address)
211{
212	const sockaddr_l2cap* address
213		= reinterpret_cast<const sockaddr_l2cap*>(_address);
214
215	if (address->l2cap_len != sizeof(*address))
216		return EINVAL;
217
218	// Check for any specific status?
219	if (fState == CONNECTING)
220		return EINPROGRESS;
221
222	// TODO: should not be in the BOUND status first?
223
224	#if 0
225	TRACE("%s: [%ld] %p->L2capEndpoint::Connect(\"%s\")\n", __func__,
226		find_thread(NULL), this,
227		ConstSocketAddress(&gL2cap4AddressModule, _address)
228		.AsString().Data());
229	#endif
230
231	// TODO: If we were bound to a specific source address
232
233	// Route, we must find a Connection descriptor with address->l2cap_address
234	hci_id hid = btCoreData->RouteConnection(address->l2cap_bdaddr);
235
236	#if 0
237	TRACE("%s: %" B_PRId32 " for route %s\n", __func__, hid,
238		bdaddrUtils::ToString(address->l2cap_bdaddr).String());
239	#endif
240
241	if (hid > 0) {
242		HciConnection* connection = btCoreData->ConnectionByDestination(
243			address->l2cap_bdaddr, hid);
244
245		L2capChannel* channel = btCoreData->AddChannel(connection,
246			address->l2cap_psm);
247
248		if (channel == NULL)
249			return ENOMEM;
250
251		// Send connection request
252		if (l2cap_upper_con_req(channel) == B_OK) {
253			fState = CONNECTING;
254
255			BindToChannel(channel);
256
257			fEstablishSemaphore = create_sem(0, "l2cap client");
258			if (fEstablishSemaphore < B_OK) {
259				ERROR("%s: Semaphore could not be created\n", __func__);
260				return ENOBUFS;
261			}
262
263			bigtime_t timeout = absolute_timeout(300 * 1000 * 1000);
264
265			return acquire_sem_etc(fEstablishSemaphore, 1,
266				B_ABSOLUTE_TIMEOUT | B_CAN_INTERRUPT, timeout);
267
268		} else {
269			return ECONNREFUSED;
270		}
271	}
272
273	return ENETUNREACH;
274}
275
276
277status_t
278L2capEndpoint::Accept(net_socket** _acceptedSocket)
279{
280	CALLED();
281
282	// MutexLocker locker(fLock);
283
284	status_t status;
285	bigtime_t timeout = absolute_timeout(300 * 1000 * 1000);
286
287	do {
288		// locker.Unlock();
289
290		status = acquire_sem_etc(fEstablishSemaphore, 1, B_ABSOLUTE_TIMEOUT
291			| B_CAN_INTERRUPT, timeout);
292
293		if (status != B_OK)
294			return status;
295
296		// locker.Lock();
297		status = gSocketModule->dequeue_connected(socket, _acceptedSocket);
298
299		if (status != B_OK) {
300			ERROR("%s: Could not dequeue socket %s\n", __func__,
301				strerror(status));
302		} else {
303
304			((L2capEndpoint*)((*_acceptedSocket)->first_protocol))->fState = ESTABLISHED;
305			// unassign any channel for the parent endpoint
306			fChannel = NULL;
307			// we are listening again
308			fState = LISTEN;
309		}
310
311	} while (status != B_OK);
312
313	return status;
314}
315
316
317ssize_t
318L2capEndpoint::Send(const iovec* vecs, size_t vecCount,
319	ancillary_data_container* ancillaryData)
320{
321	CALLED();
322
323	return B_OK;
324}
325
326
327ssize_t
328L2capEndpoint::Receive(const iovec* vecs, size_t vecCount,
329	ancillary_data_container** _ancillaryData, struct sockaddr* _address,
330	socklen_t* _addressLength)
331{
332	CALLED();
333
334	if (fState != ESTABLISHED) {
335		ERROR("%s: Invalid State %p\n", __func__, this);
336		return B_BAD_VALUE;
337	}
338
339	return B_OK;
340}
341
342
343ssize_t
344L2capEndpoint::ReadData(size_t numBytes, uint32 flags, net_buffer** _buffer)
345{
346	CALLED();
347
348	if (fState != ESTABLISHED) {
349		ERROR("%s: Invalid State %p\n", __func__, this);
350		return B_BAD_VALUE;
351	}
352
353	return gStackModule->fifo_dequeue_buffer(&fReceivingFifo, flags,
354		B_INFINITE_TIMEOUT, _buffer);
355}
356
357
358ssize_t
359L2capEndpoint::SendData(net_buffer* buffer)
360{
361	CALLED();
362
363	if (fState != ESTABLISHED) {
364		ERROR("%s: Invalid State %p\n", __func__, this);
365		return B_BAD_VALUE;
366	}
367
368	btCoreData->SpawnFrame(fChannel->conn, fChannel, buffer, L2CAP_B_FRAME);
369
370	SchedConnectionPurgeThread(fChannel->conn);
371
372	// TODO: Report bytes sent?
373	return B_OK;
374}
375
376
377ssize_t
378L2capEndpoint::Sendable()
379{
380	CALLED();
381	return B_OK;
382}
383
384
385ssize_t
386L2capEndpoint::Receivable()
387{
388	CALLED();
389	return 0;
390}
391
392
393L2capEndpoint*
394L2capEndpoint::ForPsm(uint16 psm)
395{
396	L2capEndpoint* endpoint;
397
398	DoublyLinkedList<L2capEndpoint>::Iterator iterator
399		= EndpointList.GetIterator();
400
401	while (iterator.HasNext()) {
402
403		endpoint = iterator.Next();
404		if (((struct sockaddr_l2cap*)&endpoint->socket->address)->l2cap_psm == psm
405			&& endpoint->fState == LISTEN) {
406			// TODO endpoint ocupied, lock it! define a channel for it
407			return endpoint;
408		}
409	}
410
411	return NULL;
412}
413
414
415void
416L2capEndpoint::BindNewEnpointToChannel(L2capChannel* channel)
417{
418	net_socket* newSocket;
419	status_t error = gSocketModule->spawn_pending_socket(socket, &newSocket);
420	if (error != B_OK) {
421		ERROR("%s: Could not spawn child for Endpoint %p\n", __func__, this);
422		// TODO: Handle situation
423		return;
424	}
425
426	L2capEndpoint* endpoint = (L2capEndpoint*)newSocket->first_protocol;
427
428	endpoint->fChannel = channel;
429	endpoint->fPeerEndpoint = this;
430
431	channel->endpoint = endpoint;
432
433	//debugf("new socket %p/e->%p from parent %p/e->%p\n",
434	//	newSocket, endpoint, socket, this);
435
436	// Provide the channel the configuration set by the user socket
437	channel->configuration = &fConfiguration;
438
439	// It might be used keep the last negotiated channel
440	// fChannel = channel;
441
442	//debugf("New endpoint %p for psm %d, schannel %x dchannel %x\n", endpoint,
443	//	channel->psm, channel->scid, channel->dcid);
444}
445
446
447void
448L2capEndpoint::BindToChannel(L2capChannel* channel)
449{
450	this->fChannel = channel;
451	channel->endpoint = this;
452
453	// Provide the channel the configuration set by the user socket
454	channel->configuration = &fConfiguration;
455
456	// no parent to give feedback
457	fPeerEndpoint = NULL;
458}
459
460
461status_t
462L2capEndpoint::MarkEstablished()
463{
464	CALLED();
465
466	status_t error = B_OK;
467	fChannel->state = L2CAP_CHAN_OPEN;
468	fState = ESTABLISHED;
469
470	if (fPeerEndpoint != NULL) {
471
472		error = gSocketModule->set_connected(socket);
473		if (error == B_OK) {
474			release_sem(fPeerEndpoint->fEstablishSemaphore);
475		} else {
476			ERROR("%s: Could not set child Endpoint %p %s\n", __func__, this,
477				strerror(error));
478		}
479	} else
480		release_sem(fEstablishSemaphore);
481
482	return error;
483}
484
485
486status_t
487L2capEndpoint::MarkClosed()
488{
489	CALLED();
490
491	if (fState == CLOSED)
492		release_sem(fEstablishSemaphore);
493
494	fState = CLOSED;
495
496	return B_OK;
497}
498