继续上文的socke的创建之后,我们自然而然就会想到下面的工作了,没错就是bind。
5.6 l2cap的bind分析
按照国际惯例,在建了socket之后,必然会有bind,哈哈~~
if (l2cap_bind(sock, &opts->src, server ? opts->psm : 0,
opts->cid, err) < 0)
这个函数如下:
static int l2cap_bind(int sock, const bdaddr_t *src, uint16_t psm,
uint16_t cid, GError **err)
{
struct sockaddr_l2 addr;
memset(&addr, 0, sizeof(addr));
addr.l2_family = AF_BLUETOOTH;
bacpy(&addr.l2_bdaddr, src);
//cid是0,psm是0?
if (cid)
addr.l2_cid = htobs(cid);
else
addr.l2_psm = htobs(psm);
//bind,这里仍然会调用到kernel中去,详细见5.6.1的分析
if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
ERROR_FAILED(err, "l2cap_bind", errno);
return -1;
}
return 0;
}
5.6.1 kernel中 bind的分析
static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
{
//得到对应的sock和chan
struct sock *sk = sock->sk;
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
struct sockaddr_l2 la;
int len, err = 0;
BT_DBG("sk %p", sk);
//检查一下传入的参数
if (!addr || addr->sa_family != AF_BLUETOOTH)
return -EINVAL;
memset(&la, 0, sizeof(la));
len = min_t(unsigned int, sizeof(la), alen);
//把传入的内容拷贝到la中
memcpy(&la, addr, len);
//两个不能都有值,我们两个都是0
if (la.l2_cid && la.l2_psm)
return -EINVAL;
lock_sock(sk);
//这个开始就是open,这里只是double check一下
if (sk->sk_state != BT_OPEN) {
err = -EBADFD;
goto done;
}
//若是传入了psm
if (la.l2_psm) {
__u16 psm = __le16_to_cpu(la.l2_psm);
//psm必须是奇数,并且高位是0,这个是spec规定的。具体的介绍见5.6.2
/* PSM must be odd and lsb of upper byte must be 0 */
if ((psm & 0x0101) != 0x0001) {
err = -EINVAL;
goto done;
}
/* Restrict usage of well-known PSMs */
//psm范围的检查以及权限的检查
if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) {
err = -EACCES;
goto done;
}
}
//若是有cid,就add cid,否则就add psm,关于cid的概念,我们在5.6.3中分析
if (la.l2_cid)
err = l2cap_add_scid(chan, la.l2_cid);
else
//这里不管有没有psm都是可以的,没有就生成一个,这里是psm的赋值,详细分析见5.6.4
err = l2cap_add_psm(chan, &la.l2_bdaddr, la.l2_psm);
if (err < 0)
goto done;
//这个时特殊的psm值,sdp
if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
__le16_to_cpu(la.l2_psm) == 0x0003)
chan->sec_level = BT_SECURITY_SDP;
//这里设置的是源
bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
//chan的state设为bound,就是binded了
chan->state = BT_BOUND;
sk->sk_state = BT_BOUND;
done:
release_sock(sk);
return err;
}
5.6.2 spec中psm的规定
Psm全称为Protocol/ServiceMultiplexer。在spec中是这样描述的:
The PSM fieldis at least two octets in length. The structure of the PSM field is based onthe ISO 3309 extension mechanism for address fields. All PSM values shall beODD, that is, the least significant bit of the least significant octet must be’1’. Also, all PSM values shall have the least significant bit of the mostsignificant octet equal to ’0’. This allows the PSM field to be extended beyond16 bits. PSM values are separated into two ranges. Valid values in the firstrange are assigned by the Bluetooth SIG and indicate protocols. The secondrange of values are dynamically allocated and used in conjunction with theService Discovery Protocol (SDP). The dynamically assigned value