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