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