btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / add-ons / kernel / network / protocols / l2cap / L2capEndpoint.cpp
bloba6c89f165065e41911d3bf568f37276b0bfd13a3
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"
10 #include <stdio.h>
11 #include <string.h>
12 #include <sys/stat.h>
14 #include <bluetooth/bdaddrUtils.h>
15 #include <bluetooth/L2CAP/btL2CAP.h>
17 #include <btDebug.h>
20 static inline bigtime_t
21 absolute_timeout(bigtime_t timeout)
23 if (timeout == 0 || timeout == B_INFINITE_TIMEOUT)
24 return timeout;
26 // TODO: Make overflow safe!
27 return timeout + system_time();
31 L2capEndpoint::L2capEndpoint(net_socket* socket)
33 ProtocolSocket(socket),
34 fConfigurationSet(false),
35 fEstablishSemaphore(-1),
36 fPeerEndpoint(NULL),
37 fChannel(NULL)
39 CALLED();
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) );
45 fConfiguration.omtu = L2CAP_MTU_DEFAULT;
46 memcpy(&fConfiguration.oflow, &default_qos , sizeof(l2cap_flow_t) );
48 fConfiguration.flush_timo = L2CAP_FLUSH_TIMO_DEFAULT;
49 fConfiguration.link_timo = L2CAP_LINK_TIMO_DEFAULT;
51 // TODO: XXX not for listening endpoints, imtu should be known first
52 gStackModule->init_fifo(&fReceivingFifo, "l2cap recvfifo", L2CAP_MTU_DEFAULT);
56 L2capEndpoint::~L2capEndpoint()
58 CALLED();
60 gStackModule->uninit_fifo(&fReceivingFifo);
64 status_t
65 L2capEndpoint::Init()
67 CALLED();
69 return B_OK;
73 void
74 L2capEndpoint::Uninit()
76 CALLED();
81 status_t
82 L2capEndpoint::Open()
84 CALLED();
86 status_t error = ProtocolSocket::Open();
87 if (error != B_OK)
88 return error;
90 return B_OK;
94 status_t
95 L2capEndpoint::Close()
97 CALLED();
99 if (fChannel == NULL) {
100 // TODO: Parent socket
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();
111 bigtime_t timeout = absolute_timeout(300 * 1000 * 1000);
113 status_t error = l2cap_upper_dis_req(fChannel);
115 if (error != B_OK)
116 return error;
118 return acquire_sem_etc(fEstablishSemaphore, 1,
119 B_ABSOLUTE_TIMEOUT | B_CAN_INTERRUPT, timeout);
123 if (fEstablishSemaphore != -1) {
124 delete_sem(fEstablishSemaphore);
127 return B_OK;
131 status_t
132 L2capEndpoint::Free()
134 CALLED();
136 return B_OK;
140 status_t
141 L2capEndpoint::Bind(const struct sockaddr* _address)
143 const sockaddr_l2cap* address
144 = reinterpret_cast<const sockaddr_l2cap*>(_address);
146 if (_address == NULL)
147 return B_ERROR;
149 if (address->l2cap_family != AF_BLUETOOTH )
150 return EAFNOSUPPORT;
152 if (address->l2cap_len != sizeof(struct sockaddr_l2cap))
153 return EAFNOSUPPORT;
155 // TODO: Check if that PSM is already bound
156 // return EADDRINUSE;
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;
167 memcpy(&socket->address, _address, sizeof(struct sockaddr_l2cap));
168 socket->address.ss_len = sizeof(struct sockaddr_l2cap);
170 fState = BOUND;
172 return B_OK;
176 status_t
177 L2capEndpoint::Unbind()
179 CALLED();
181 return B_OK;
185 status_t
186 L2capEndpoint::Listen(int backlog)
188 CALLED();
190 if (fState != BOUND) {
191 ERROR("%s: Invalid State\n", __func__);
192 return B_BAD_VALUE;
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;
201 gSocketModule->set_max_backlog(socket, backlog);
203 fState = LISTEN;
205 return B_OK;
209 status_t
210 L2capEndpoint::Connect(const struct sockaddr* _address)
212 const sockaddr_l2cap* address
213 = reinterpret_cast<const sockaddr_l2cap*>(_address);
215 if (address->l2cap_len != sizeof(*address))
216 return EINVAL;
218 // Check for any specific status?
219 if (fState == CONNECTING)
220 return EINPROGRESS;
222 // TODO: should not be in the BOUND status first?
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
231 // TODO: If we were bound to a specific source address
233 // Route, we must find a Connection descriptor with address->l2cap_address
234 hci_id hid = btCoreData->RouteConnection(address->l2cap_bdaddr);
236 #if 0
237 TRACE("%s: %" B_PRId32 " for route %s\n", __func__, hid,
238 bdaddrUtils::ToString(address->l2cap_bdaddr).String());
239 #endif
241 if (hid > 0) {
242 HciConnection* connection = btCoreData->ConnectionByDestination(
243 address->l2cap_bdaddr, hid);
245 L2capChannel* channel = btCoreData->AddChannel(connection,
246 address->l2cap_psm);
248 if (channel == NULL)
249 return ENOMEM;
251 // Send connection request
252 if (l2cap_upper_con_req(channel) == B_OK) {
253 fState = CONNECTING;
255 BindToChannel(channel);
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;
263 bigtime_t timeout = absolute_timeout(300 * 1000 * 1000);
265 return acquire_sem_etc(fEstablishSemaphore, 1,
266 B_ABSOLUTE_TIMEOUT | B_CAN_INTERRUPT, timeout);
268 } else {
269 return ECONNREFUSED;
273 return ENETUNREACH;
277 status_t
278 L2capEndpoint::Accept(net_socket** _acceptedSocket)
280 CALLED();
282 // MutexLocker locker(fLock);
284 status_t status;
285 bigtime_t timeout = absolute_timeout(300 * 1000 * 1000);
287 do {
288 // locker.Unlock();
290 status = acquire_sem_etc(fEstablishSemaphore, 1, B_ABSOLUTE_TIMEOUT
291 | B_CAN_INTERRUPT, timeout);
293 if (status != B_OK)
294 return status;
296 // locker.Lock();
297 status = gSocketModule->dequeue_connected(socket, _acceptedSocket);
299 if (status != B_OK) {
300 ERROR("%s: Could not dequeue socket %s\n", __func__,
301 strerror(status));
302 } else {
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;
311 } while (status != B_OK);
313 return status;
317 ssize_t
318 L2capEndpoint::Send(const iovec* vecs, size_t vecCount,
319 ancillary_data_container* ancillaryData)
321 CALLED();
323 return B_OK;
327 ssize_t
328 L2capEndpoint::Receive(const iovec* vecs, size_t vecCount,
329 ancillary_data_container** _ancillaryData, struct sockaddr* _address,
330 socklen_t* _addressLength)
332 CALLED();
334 if (fState != ESTABLISHED) {
335 ERROR("%s: Invalid State %p\n", __func__, this);
336 return B_BAD_VALUE;
339 return B_OK;
343 ssize_t
344 L2capEndpoint::ReadData(size_t numBytes, uint32 flags, net_buffer** _buffer)
346 CALLED();
348 if (fState != ESTABLISHED) {
349 ERROR("%s: Invalid State %p\n", __func__, this);
350 return B_BAD_VALUE;
353 return gStackModule->fifo_dequeue_buffer(&fReceivingFifo, flags,
354 B_INFINITE_TIMEOUT, _buffer);
358 ssize_t
359 L2capEndpoint::SendData(net_buffer* buffer)
361 CALLED();
363 if (fState != ESTABLISHED) {
364 ERROR("%s: Invalid State %p\n", __func__, this);
365 return B_BAD_VALUE;
368 btCoreData->SpawnFrame(fChannel->conn, fChannel, buffer, L2CAP_B_FRAME);
370 SchedConnectionPurgeThread(fChannel->conn);
372 // TODO: Report bytes sent?
373 return B_OK;
377 ssize_t
378 L2capEndpoint::Sendable()
380 CALLED();
381 return B_OK;
385 ssize_t
386 L2capEndpoint::Receivable()
388 CALLED();
389 return 0;
393 L2capEndpoint*
394 L2capEndpoint::ForPsm(uint16 psm)
396 L2capEndpoint* endpoint;
398 DoublyLinkedList<L2capEndpoint>::Iterator iterator
399 = EndpointList.GetIterator();
401 while (iterator.HasNext()) {
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;
411 return NULL;
415 void
416 L2capEndpoint::BindNewEnpointToChannel(L2capChannel* channel)
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;
426 L2capEndpoint* endpoint = (L2capEndpoint*)newSocket->first_protocol;
428 endpoint->fChannel = channel;
429 endpoint->fPeerEndpoint = this;
431 channel->endpoint = endpoint;
433 //debugf("new socket %p/e->%p from parent %p/e->%p\n",
434 // newSocket, endpoint, socket, this);
436 // Provide the channel the configuration set by the user socket
437 channel->configuration = &fConfiguration;
439 // It might be used keep the last negotiated channel
440 // fChannel = channel;
442 //debugf("New endpoint %p for psm %d, schannel %x dchannel %x\n", endpoint,
443 // channel->psm, channel->scid, channel->dcid);
447 void
448 L2capEndpoint::BindToChannel(L2capChannel* channel)
450 this->fChannel = channel;
451 channel->endpoint = this;
453 // Provide the channel the configuration set by the user socket
454 channel->configuration = &fConfiguration;
456 // no parent to give feedback
457 fPeerEndpoint = NULL;
461 status_t
462 L2capEndpoint::MarkEstablished()
464 CALLED();
466 status_t error = B_OK;
467 fChannel->state = L2CAP_CHAN_OPEN;
468 fState = ESTABLISHED;
470 if (fPeerEndpoint != NULL) {
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));
479 } else
480 release_sem(fEstablishSemaphore);
482 return error;
486 status_t
487 L2capEndpoint::MarkClosed()
489 CALLED();
491 if (fState == CLOSED)
492 release_sem(fEstablishSemaphore);
494 fState = CLOSED;
496 return B_OK;