- 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:
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user