xref: /haiku/src/add-ons/kernel/network/protocols/l2cap/L2capEndpoint.cpp (revision a3e794ae459fec76826407f8ba8c94cd3535f128)
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 
20 static inline bigtime_t
21 absolute_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 
31 L2capEndpoint::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 
56 L2capEndpoint::~L2capEndpoint()
57 {
58 	CALLED();
59 
60 	gStackModule->uninit_fifo(&fReceivingFifo);
61 }
62 
63 
64 status_t
65 L2capEndpoint::Init()
66 {
67 	CALLED();
68 
69 	return B_OK;
70 }
71 
72 
73 void
74 L2capEndpoint::Uninit()
75 {
76 	CALLED();
77 
78 }
79 
80 
81 status_t
82 L2capEndpoint::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 
94 status_t
95 L2capEndpoint::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 
131 status_t
132 L2capEndpoint::Free()
133 {
134 	CALLED();
135 
136 	return B_OK;
137 }
138 
139 
140 status_t
141 L2capEndpoint::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 
176 status_t
177 L2capEndpoint::Unbind()
178 {
179 	CALLED();
180 
181 	return B_OK;
182 }
183 
184 
185 status_t
186 L2capEndpoint::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 
209 status_t
210 L2capEndpoint::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 
277 status_t
278 L2capEndpoint::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 
317 ssize_t
318 L2capEndpoint::Send(const iovec* vecs, size_t vecCount,
319 	ancillary_data_container* ancillaryData)
320 {
321 	CALLED();
322 
323 	return B_OK;
324 }
325 
326 
327 ssize_t
328 L2capEndpoint::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 
343 ssize_t
344 L2capEndpoint::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 
358 ssize_t
359 L2capEndpoint::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 
377 ssize_t
378 L2capEndpoint::Sendable()
379 {
380 	CALLED();
381 	return B_OK;
382 }
383 
384 
385 ssize_t
386 L2capEndpoint::Receivable()
387 {
388 	CALLED();
389 	return 0;
390 }
391 
392 
393 L2capEndpoint*
394 L2capEndpoint::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 
415 void
416 L2capEndpoint::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 
447 void
448 L2capEndpoint::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 
461 status_t
462 L2capEndpoint::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 
486 status_t
487 L2capEndpoint::MarkClosed()
488 {
489 	CALLED();
490 
491 	if (fState == CLOSED)
492 		release_sem(fEstablishSemaphore);
493 
494 	fState = CLOSED;
495 
496 	return B_OK;
497 }
498