Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
Show First 20 Lines • Show All 1,143 Lines • ▼ Show 20 Lines | |||||
* Process RFCOMM connection indicator. Caller must hold s->session_mtx | * Process RFCOMM connection indicator. Caller must hold s->session_mtx | ||||
*/ | */ | ||||
static ng_btsocket_rfcomm_pcb_p | static ng_btsocket_rfcomm_pcb_p | ||||
ng_btsocket_rfcomm_connect_ind(ng_btsocket_rfcomm_session_p s, int channel) | ng_btsocket_rfcomm_connect_ind(ng_btsocket_rfcomm_session_p s, int channel) | ||||
{ | { | ||||
ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL; | ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL; | ||||
ng_btsocket_l2cap_pcb_p l2pcb = NULL; | ng_btsocket_l2cap_pcb_p l2pcb = NULL; | ||||
struct socket *so1 = NULL; | struct socket *so1; | ||||
mtx_assert(&s->session_mtx, MA_OWNED); | mtx_assert(&s->session_mtx, MA_OWNED); | ||||
/* | /* | ||||
* Try to find RFCOMM socket that listens on given source address | * Try to find RFCOMM socket that listens on given source address | ||||
* and channel. This will return the best possible match. | * and channel. This will return the best possible match. | ||||
*/ | */ | ||||
l2pcb = so2l2cap_pcb(s->l2so); | l2pcb = so2l2cap_pcb(s->l2so); | ||||
pcb = ng_btsocket_rfcomm_pcb_listener(&l2pcb->src, channel); | pcb = ng_btsocket_rfcomm_pcb_listener(&l2pcb->src, channel); | ||||
if (pcb == NULL) | if (pcb == NULL) | ||||
return (NULL); | return (NULL); | ||||
/* | /* | ||||
* Check the pending connections queue and if we have space then | * Check the pending connections queue and if we have space then | ||||
* create new socket and set proper source and destination address, | * create new socket and set proper source and destination address, | ||||
* and channel. | * and channel. | ||||
*/ | */ | ||||
mtx_lock(&pcb->pcb_mtx); | mtx_lock(&pcb->pcb_mtx); | ||||
if (pcb->so->so_qlen <= pcb->so->so_qlimit) { | |||||
CURVNET_SET(pcb->so->so_vnet); | CURVNET_SET(pcb->so->so_vnet); | ||||
so1 = sonewconn(pcb->so, 0); | so1 = sonewconn(pcb->so, 0); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
} | |||||
mtx_unlock(&pcb->pcb_mtx); | mtx_unlock(&pcb->pcb_mtx); | ||||
if (so1 == NULL) | if (so1 == NULL) | ||||
return (NULL); | return (NULL); | ||||
/* | /* | ||||
* If we got here than we have created new socket. So complete the | * If we got here than we have created new socket. So complete the | ||||
▲ Show 20 Lines • Show All 213 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Process accept() on RFCOMM session | * Process accept() on RFCOMM session | ||||
* XXX FIXME locking for "l2so"? | * XXX FIXME locking for "l2so"? | ||||
*/ | */ | ||||
static int | static int | ||||
ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0) | ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0) | ||||
{ | { | ||||
struct socket *l2so = NULL; | struct socket *l2so; | ||||
struct sockaddr_l2cap *l2sa = NULL; | struct sockaddr_l2cap *l2sa = NULL; | ||||
ng_btsocket_l2cap_pcb_t *l2pcb = NULL; | ng_btsocket_l2cap_pcb_t *l2pcb = NULL; | ||||
ng_btsocket_rfcomm_session_p s = NULL; | ng_btsocket_rfcomm_session_p s = NULL; | ||||
int error = 0; | int error; | ||||
mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED); | mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED); | ||||
mtx_assert(&s0->session_mtx, MA_OWNED); | mtx_assert(&s0->session_mtx, MA_OWNED); | ||||
/* Check if there is a complete L2CAP connection in the queue */ | SOLISTEN_LOCK(s0->l2so); | ||||
if ((error = s0->l2so->so_error) != 0) { | error = solisten_dequeue(s0->l2so, &l2so, 0); | ||||
if (error == EWOULDBLOCK) | |||||
return (error); | |||||
if (error) { | |||||
NG_BTSOCKET_RFCOMM_ERR( | NG_BTSOCKET_RFCOMM_ERR( | ||||
"%s: Could not accept connection on L2CAP socket, error=%d\n", __func__, error); | "%s: Could not accept connection on L2CAP socket, error=%d\n", __func__, error); | ||||
s0->l2so->so_error = 0; | |||||
return (error); | return (error); | ||||
} | } | ||||
ACCEPT_LOCK(); | |||||
if (TAILQ_EMPTY(&s0->l2so->so_comp)) { | |||||
ACCEPT_UNLOCK(); | |||||
if (s0->l2so->so_rcv.sb_state & SBS_CANTRCVMORE) | |||||
return (ECONNABORTED); | |||||
return (EWOULDBLOCK); | |||||
} | |||||
/* Accept incoming L2CAP connection */ | |||||
l2so = TAILQ_FIRST(&s0->l2so->so_comp); | |||||
if (l2so == NULL) | |||||
panic("%s: l2so == NULL\n", __func__); | |||||
TAILQ_REMOVE(&s0->l2so->so_comp, l2so, so_list); | |||||
s0->l2so->so_qlen --; | |||||
l2so->so_qstate &= ~SQ_COMP; | |||||
l2so->so_head = NULL; | |||||
SOCK_LOCK(l2so); | |||||
soref(l2so); | |||||
l2so->so_state |= SS_NBIO; | |||||
SOCK_UNLOCK(l2so); | |||||
ACCEPT_UNLOCK(); | |||||
error = soaccept(l2so, (struct sockaddr **) &l2sa); | error = soaccept(l2so, (struct sockaddr **) &l2sa); | ||||
if (error != 0) { | if (error != 0) { | ||||
NG_BTSOCKET_RFCOMM_ERR( | NG_BTSOCKET_RFCOMM_ERR( | ||||
"%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error); | "%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error); | ||||
soclose(l2so); | soclose(l2so); | ||||
return (error); | return (error); | ||||
▲ Show 20 Lines • Show All 2,127 Lines • Show Last 20 Lines |