- 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
This commit is contained in:
Oliver Ruiz Dorantes
2010-07-12 22:08:11 +00:00
parent aa9a027532
commit 8638173cff
7 changed files with 103 additions and 31 deletions
@@ -5,6 +5,7 @@
#include "L2capEndpoint.h"
#include "l2cap_address.h"
#include "l2cap_upper.h"
#include "l2cap_lower.h"
#include <stdio.h>
#include <string.h>
@@ -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;
}
@@ -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();
@@ -101,8 +101,12 @@ l2cap_open(net_protocol* protocol)
status_t
l2cap_close(net_protocol* protocol)
{
L2capEndpoint* endpoint = static_cast<L2capEndpoint*>(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);
}
@@ -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);
@@ -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 */
@@ -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);
}
@@ -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);