From 8638173cff5388cb3bbbc67e7d77977d1f69eb03 Mon Sep 17 00:00:00 2001 From: Oliver Ruiz Dorantes Date: Mon, 12 Jul 2010 22:08:11 +0000 Subject: [PATCH] - Implementation for sendto() & close(), tested over a Motorola V5 - Incomming command rejections not yet properly handled. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37486 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../network/protocols/l2cap/L2capEndpoint.cpp | 58 ++++++++++++++----- .../network/protocols/l2cap/L2capEndpoint.h | 1 + .../kernel/network/protocols/l2cap/l2cap.cpp | 9 ++- .../network/protocols/l2cap/l2cap_lower.cpp | 14 ++++- .../network/protocols/l2cap/l2cap_signal.cpp | 22 +++---- .../network/protocols/l2cap/l2cap_upper.cpp | 25 ++++++-- .../network/protocols/l2cap/l2cap_upper.h | 5 +- 7 files changed, 103 insertions(+), 31 deletions(-) diff --git a/src/add-ons/kernel/network/protocols/l2cap/L2capEndpoint.cpp b/src/add-ons/kernel/network/protocols/l2cap/L2capEndpoint.cpp index 7ebc57a9d4..7f847154c8 100644 --- a/src/add-ons/kernel/network/protocols/l2cap/L2capEndpoint.cpp +++ b/src/add-ons/kernel/network/protocols/l2cap/L2capEndpoint.cpp @@ -5,6 +5,7 @@ #include "L2capEndpoint.h" #include "l2cap_address.h" #include "l2cap_upper.h" +#include "l2cap_lower.h" #include #include @@ -99,28 +100,36 @@ L2capEndpoint::Close() { debugf("[%ld] %p\n", find_thread(NULL), this); - if (fEstablishSemaphore != -1) { - debugf("server socket not handling any channel %p\n", this); - - delete_sem(fEstablishSemaphore); - // TODO: Clean needed stuff - // Unbind? - return B_OK; + if (fChannel == NULL) { + // TODO: Parent socket } else { - // Client endpoint - if (fState == CLOSING) { + // Child Socket + if (fState == CLOSED) { debugf("Already closed by peer %p\n", this); // TODO: Clean needed stuff - return B_OK; } else { // Issue Disconnection request over the channel - fState = CLOSED; - return l2cap_upper_dis_req(fChannel); + MarkClosed(); + + bigtime_t timeout = absolute_timeout(300 * 1000 * 1000); + + status_t error = l2cap_upper_dis_req(fChannel); + + if (error != B_OK) + return error; + + return acquire_sem_etc(fEstablishSemaphore, 1, + B_ABSOLUTE_TIMEOUT | B_CAN_INTERRUPT, timeout); } } + if (fEstablishSemaphore != -1) { + delete_sem(fEstablishSemaphore); + } + + return B_OK; } @@ -351,6 +360,25 @@ L2capEndpoint::ReadData(size_t numBytes, uint32 flags, net_buffer** _buffer) } +ssize_t +L2capEndpoint::SendData(net_buffer* buffer) +{ + debugf("size=%ld\n", buffer->size); + + if (fState != ESTABLISHED) { + debugf("Invalid State %p\n", this); + return B_BAD_VALUE; + } + + btCoreData->SpawnFrame(fChannel->conn, fChannel, buffer, L2CAP_B_FRAME); + + SchedConnectionPurgeThread(fChannel->conn); + + // TODO: Report bytes sent? + return B_OK; +} + + ssize_t L2capEndpoint::Sendable() { @@ -445,6 +473,7 @@ L2capEndpoint::MarkEstablished() fChannel->psm, fChannel->scid, fChannel->dcid); fChannel->state = L2CAP_CHAN_OPEN; + fState = ESTABLISHED; if (fPeerEndpoint != NULL) { @@ -465,8 +494,11 @@ status_t L2capEndpoint::MarkClosed() { flowf("\n"); + if (fState == CLOSED) { + release_sem(fEstablishSemaphore); + } + fState = CLOSED; return B_OK; } - diff --git a/src/add-ons/kernel/network/protocols/l2cap/L2capEndpoint.h b/src/add-ons/kernel/network/protocols/l2cap/L2capEndpoint.h index 2d18e55aee..ddc30243d1 100644 --- a/src/add-ons/kernel/network/protocols/l2cap/L2capEndpoint.h +++ b/src/add-ons/kernel/network/protocols/l2cap/L2capEndpoint.h @@ -57,6 +57,7 @@ public: struct sockaddr* _address, socklen_t* _addressLength); ssize_t ReadData(size_t numBytes, uint32 flags, net_buffer** _buffer); + ssize_t SendData(net_buffer* buffer); ssize_t Sendable(); ssize_t Receivable(); diff --git a/src/add-ons/kernel/network/protocols/l2cap/l2cap.cpp b/src/add-ons/kernel/network/protocols/l2cap/l2cap.cpp index 0736255c23..18122e864e 100644 --- a/src/add-ons/kernel/network/protocols/l2cap/l2cap.cpp +++ b/src/add-ons/kernel/network/protocols/l2cap/l2cap.cpp @@ -101,8 +101,12 @@ l2cap_open(net_protocol* protocol) status_t l2cap_close(net_protocol* protocol) { + L2capEndpoint* endpoint = static_cast(protocol); + flowf("\n"); + endpoint->Close(); + return B_OK; } @@ -210,7 +214,10 @@ l2cap_send_data(net_protocol* protocol, net_buffer* buffer) { flowf("\n"); - return EOPNOTSUPP; + if (buffer == NULL) + return ENOBUFS; + + return ((L2capEndpoint*)protocol)->SendData(buffer); } diff --git a/src/add-ons/kernel/network/protocols/l2cap/l2cap_lower.cpp b/src/add-ons/kernel/network/protocols/l2cap/l2cap_lower.cpp index c62a6eee56..67066f2ed8 100644 --- a/src/add-ons/kernel/network/protocols/l2cap/l2cap_lower.cpp +++ b/src/add-ons/kernel/network/protocols/l2cap/l2cap_lower.cpp @@ -43,6 +43,15 @@ l2cap_receive(HciConnection* conn, net_buffer* buffer) uint16 dcid; uint16 length; +#ifdef DUMP_L2CAP_FRAME + flowf("DUMP:"); + for (uint i = 0; i < buffer->size; i++) { + uint8 c = 0; + gBufferModule->read(buffer, i, &c, 1); + dprintf("[%x]", c); + } + dprintf("\n"); +#endif // Check packet if (buffer->size < sizeof(l2cap_hdr_t)) { debugf("invalid L2CAP packet. Packet too small, len=%ld\n", buffer->size); @@ -61,6 +70,8 @@ l2cap_receive(HciConnection* conn, net_buffer* buffer) length = bufferHeader->length = le16toh(bufferHeader->length); dcid = bufferHeader->dcid = le16toh(bufferHeader->dcid); + debugf("len=%d cid=%x\n", length, dcid); + bufferHeader.Remove(); // pulling // Check payload size @@ -165,7 +176,8 @@ purge_connection(HciConnection* conn) } // TODO: someone put it - debugf("code=%d frame %p tolower\n", frame->code, frame->buffer); + debugf("type=%d, code=%d frame %p tolower\n", frame->type, frame->code, + frame->buffer); frame->buffer->type = conn->handle; btDevices->PostACL(conn->ndevice->index, frame->buffer); diff --git a/src/add-ons/kernel/network/protocols/l2cap/l2cap_signal.cpp b/src/add-ons/kernel/network/protocols/l2cap/l2cap_signal.cpp index 1e9d2569e2..95e24f5b79 100644 --- a/src/add-ons/kernel/network/protocols/l2cap/l2cap_signal.cpp +++ b/src/add-ons/kernel/network/protocols/l2cap/l2cap_signal.cpp @@ -120,19 +120,19 @@ l2cap_process_signal_cmd(HciConnection* conn, net_buffer* buffer) return ENOBUFS; } - commandHeader->length = le16toh(commandHeader->length); + uint8 processingCode = commandHeader->code; + uint8 processingIdent = commandHeader->ident; + uint16 processingLength = le16toh(commandHeader->length); /* Verify command length */ - if (buffer->size < commandHeader->length) { + if (buffer->size < processingLength) { debugf("invalid L2CAP signaling command, code=%#x, ident=%d," - " length=%d, buffer size=%ld\n", commandHeader->code, - commandHeader->ident, commandHeader->length, buffer->size); + " length=%d, buffer size=%ld\n", processingCode, + processingIdent, processingLength, buffer->size); gBufferModule->free(buffer); return (EMSGSIZE); } - uint8 processingCode = commandHeader->code; - uint16 processingIdent = commandHeader->ident; commandHeader.Remove(); // pulling the header of the command @@ -761,7 +761,7 @@ l2cap_process_discon_req(HciConnection* conn, uint8 ident, net_buffer* buffer) // inform upper if we were not actually already waiting if (channel->state != L2CAP_CHAN_W4_L2CAP_DISCON_RSP) { - l2cap_l2ca_discon_ind(channel); // do not care about result + l2cap_discon_req_ind(channel); // do not care about result } /* Send L2CAP_DisconnectRsp */ @@ -773,8 +773,6 @@ l2cap_process_discon_req(HciConnection* conn, uint8 ident, net_buffer* buffer) /* Link command to the queue */ SchedConnectionPurgeThread(conn); - btCoreData->RemoveChannel(conn, channel->scid); - return B_OK; reject: @@ -816,7 +814,7 @@ l2cap_process_discon_rsp(HciConnection* conn, uint8 ident, net_buffer* buffer) } /* Verify channel state, do nothing if invalid */ - if (cmd->channel->state != L2CAP_CHAN_W4_L2CAP_DISCON_RSP) { + if (cmd->channel->state != L2CAP_CHAN_W4_L2CA_DISCON_RSP) { debugf("unexpected L2CAP_DisconnectRsp. Invalid state, cid=%d, " "state=%d\n", scid, cmd->channel->state); goto out; @@ -839,7 +837,7 @@ l2cap_process_discon_rsp(HciConnection* conn, uint8 ident, net_buffer* buffer) if ((error = btCoreData->UnTimeoutSignal(cmd)) != 0) goto out; - //INDICATION = ng_l2cap_l2ca_discon_rsp(cmd->channel, cmd->token, NG_L2CAP_SUCCESS); + l2cap_discon_rsp_ind(cmd->channel/* results? */); btCoreData->RemoveChannel(conn, scid); /* this will free commands too */ out: @@ -1015,6 +1013,8 @@ l2cap_process_cmd_rej(HciConnection* conn, uint8 ident, net_buffer* buffer) command->reason = le16toh(command->reason); + debugf("reason=%d\n", command->reason); + command.Remove(); /* Check if we have pending command descriptor */ diff --git a/src/add-ons/kernel/network/protocols/l2cap/l2cap_upper.cpp b/src/add-ons/kernel/network/protocols/l2cap/l2cap_upper.cpp index 050e44bcfb..b58eea999c 100644 --- a/src/add-ons/kernel/network/protocols/l2cap/l2cap_upper.cpp +++ b/src/add-ons/kernel/network/protocols/l2cap/l2cap_upper.cpp @@ -209,12 +209,26 @@ l2cap_cfg_req_ind(L2capChannel* channel) status_t -l2cap_l2ca_discon_ind(L2capChannel* channel) +l2cap_discon_req_ind(L2capChannel* channel) { return channel->endpoint->MarkClosed(); } +status_t +l2cap_discon_rsp_ind(L2capChannel* channel) +{ + if (channel->state == L2CAP_CHAN_W4_L2CA_DISCON_RSP) { + channel->endpoint->MarkClosed(); + } + + return B_OK; +} + + + + + #if 0 #pragma mark - Signals from Upper Layer #endif @@ -247,8 +261,8 @@ l2cap_upper_dis_req(L2capChannel* channel) { channel->ident = btCoreData->ChannelAllocateIdent(channel->conn); - net_buffer* buf = l2cap_discon_req(channel->ident, channel->scid, - channel->dcid); + net_buffer* buf = l2cap_discon_req(channel->ident, channel->dcid, + channel->scid); L2capFrame* cmd = btCoreData->SpawnSignal(channel->conn, channel, buf, channel->ident, L2CAP_DISCON_REQ); if (cmd == NULL) { @@ -273,7 +287,7 @@ l2cap_upper_dis_req(L2capChannel* channel) status_t l2cap_co_receive(HciConnection* conn, net_buffer* buffer, uint16 dcid) { - debugf("Handle %d To dcid %d\n", conn->handle, dcid); + debugf("Handle %d To dcid %x size=%ld\n", conn->handle, dcid, buffer->size); L2capChannel* channel = btCoreData->ChannelBySourceID(conn, dcid); @@ -306,3 +320,6 @@ l2cap_cl_receive(HciConnection* conn, net_buffer* buffer, uint16 psm) return gStackModule->fifo_enqueue_buffer( &endpoint->fReceivingFifo, buffer); } + + + diff --git a/src/add-ons/kernel/network/protocols/l2cap/l2cap_upper.h b/src/add-ons/kernel/network/protocols/l2cap/l2cap_upper.h index 803f60e9cb..c1c555b3a8 100644 --- a/src/add-ons/kernel/network/protocols/l2cap/l2cap_upper.h +++ b/src/add-ons/kernel/network/protocols/l2cap/l2cap_upper.h @@ -9,7 +9,9 @@ status_t l2cap_l2ca_con_ind(L2capChannel* channel); status_t l2cap_cfg_req_ind(L2capChannel* channel); -status_t l2cap_l2ca_discon_ind(L2capChannel* channel); +status_t l2cap_discon_req_ind(L2capChannel* channel); +status_t l2cap_discon_rsp_ind(L2capChannel* channel); + status_t l2cap_con_rsp_ind(HciConnection* conn, L2capChannel* channel); status_t l2cap_cfg_rsp_ind(L2capChannel* channel); @@ -17,6 +19,7 @@ status_t l2cap_upper_con_req(L2capChannel* channel); status_t l2cap_upper_dis_req(L2capChannel* channel); + status_t l2cap_co_receive(HciConnection* conn, net_buffer* buffer, uint16 dcid); status_t l2cap_cl_receive(HciConnection* conn, net_buffer* buffer, uint16 psm);