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