xref: /haiku/src/add-ons/kernel/network/protocols/l2cap/L2capEndpoint.cpp (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
1 /*
2  * Copyright 2008, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Oliver Ruiz Dorantes, oliver-ruiz.dorantes_at_gmail.com
7  */
8 #include "L2capEndpoint.h"
9 #include "l2cap_address.h"
10 
11 #include <stdio.h>
12 #include <string.h>
13 #include <sys/stat.h>
14 
15 
16 #include <bluetooth/L2CAP/btL2CAP.h>
17 #define BT_DEBUG_THIS_MODULE
18 #include <btDebug.h>
19 
20 
21 static inline bigtime_t
22 absolute_timeout(bigtime_t timeout)
23 {
24 	if (timeout == 0 || timeout == B_INFINITE_TIMEOUT)
25 		return timeout;
26 
27 	// TODO: Make overflow safe!
28 	return timeout + system_time();
29 }
30 
31 
32 L2capEndpoint::L2capEndpoint(net_socket* socket)
33 	:
34 	ProtocolSocket(socket),
35 	fPeerEndpoint(NULL),
36 	fAcceptSemaphore(-1)
37 {
38 	debugf("[%ld] %p->L2capEndpoint::L2capEndpoint()\n", find_thread(NULL), this);
39 
40 	/* Set MTU and flow control settings to defaults */
41 	configuration.imtu = L2CAP_MTU_DEFAULT;
42 	memcpy(&configuration.iflow, &default_qos , sizeof(l2cap_flow_t) );
43 
44 	configuration.omtu = L2CAP_MTU_DEFAULT;
45 	memcpy(&configuration.oflow, &default_qos , sizeof(l2cap_flow_t) );
46 
47 	configuration.flush_timo = L2CAP_FLUSH_TIMO_DEFAULT;
48 	configuration.link_timo  = L2CAP_LINK_TIMO_DEFAULT;
49 
50 	configurationSet = false;
51 
52 	gStackModule->init_fifo(&fReceivingFifo, "l2cap recvfifo", L2CAP_MTU_DEFAULT);
53 }
54 
55 
56 L2capEndpoint::~L2capEndpoint()
57 {
58 	debugf("[%ld] %p->L2capEndpoint::~L2capEndpoint()\n", find_thread(NULL), this);
59 
60 
61 }
62 
63 
64 status_t
65 L2capEndpoint::Init()
66 {
67 	debugf("[%ld] %p->L2capEndpoint::Init()\n", find_thread(NULL), this);
68 
69 	return B_OK;
70 }
71 
72 
73 void
74 L2capEndpoint::Uninit()
75 {
76 	debugf("[%ld] %p->L2capEndpoint::Uninit()\n", find_thread(NULL), this);
77 
78 }
79 
80 
81 status_t
82 L2capEndpoint::Open()
83 {
84 	debugf("[%ld] %p->L2capEndpoint::Open()\n", find_thread(NULL), this);
85 
86 	status_t error = ProtocolSocket::Open();
87 	if (error != B_OK)
88 		return error;
89 
90 	return B_OK;
91 }
92 
93 
94 status_t
95 L2capEndpoint::Close()
96 {
97 	debugf("[%ld] %p->L2capEndpoint::Close()\n", find_thread(NULL), this);
98 
99 	return B_OK;
100 }
101 
102 
103 status_t
104 L2capEndpoint::Free()
105 {
106 	debugf("[%ld] %p->L2capEndpoint::Free()\n", find_thread(NULL), this);
107 
108 	return B_OK;
109 }
110 
111 
112 status_t
113 L2capEndpoint::Bind(const struct sockaddr *_address)
114 {
115 	if (_address == NULL)
116 		panic("null adrresss!");
117 
118 	if (_address->sa_family != AF_BLUETOOTH )
119 		return EAFNOSUPPORT;
120 
121 	// TODO: Check socladdr_l2cap size
122 
123 	// TODO: Check if that PSM is already bound
124 	// return EADDRINUSE;
125 
126 
127 	// TODO: Check if the PSM is valid, check assigned numbers document for valid
128 	// psm available to applications.
129 	// All PSM values shall be ODD, that is, the least significant bit of the least
130 	// significant octet must be ’1’. Also, all PSM values shall have the least
131 	// significant bit of the most significant octet equal to ’0’. This allows the
132 	// PSM field to be extended beyond 16 bits.
133 	if ((((struct sockaddr_l2cap*)_address)->l2cap_psm & 1) == 0)
134 		return B_ERROR;
135 
136 	flowf("\n")
137 	memcpy(&socket->address, _address, sizeof(struct sockaddr_l2cap));
138 	socket->address.ss_len = sizeof(struct sockaddr_l2cap);
139 
140 	fState = LISTEN;
141 
142 	return B_OK;
143 
144 }
145 
146 
147 status_t
148 L2capEndpoint::Unbind()
149 {
150 	debugf("[%ld] %p->L2capEndpoint::Unbind()\n", find_thread(NULL), this);
151 
152 	return B_OK;
153 }
154 
155 
156 status_t
157 L2capEndpoint::Listen(int backlog)
158 {
159 	if (fState != CLOSED)
160 		return B_BAD_VALUE;
161 
162 	fAcceptSemaphore = create_sem(0, "tcp accept");
163 	if (fAcceptSemaphore < B_OK)
164 		return ENOBUFS;
165 
166 	fState = LISTEN;
167 
168 	return B_OK;
169 }
170 
171 
172 status_t
173 L2capEndpoint::Connect(const struct sockaddr *_address)
174 {
175 	if (_address->sa_family != AF_BLUETOOTH)
176 		return EAFNOSUPPORT;
177 
178 	debugf("[%ld] %p->L2capEndpoint::Connect(\"%s\")\n", find_thread(NULL), this,
179 		ConstSocketAddress(&gL2cap4AddressModule, _address).AsString().Data());
180 
181 	const sockaddr_l2cap* address = (const sockaddr_l2cap*)_address;
182 
183 	/**/
184 	TOUCH(address);
185 
186 	return B_OK;
187 }
188 
189 
190 status_t
191 L2capEndpoint::Accept(net_socket **_acceptedSocket)
192 {
193 	debugf("[%ld] %p->L2capEndpoint::Accept()\n", find_thread(NULL), this);
194 
195 	bigtime_t timeout = absolute_timeout(socket->receive.timeout);
196 
197 	TOUCH(timeout);
198 	return B_OK;
199 }
200 
201 
202 ssize_t
203 L2capEndpoint::Send(const iovec *vecs, size_t vecCount,
204 	ancillary_data_container *ancillaryData)
205 {
206 	debugf("[%ld] %p->L2capEndpoint::Send(%p, %ld, %p)\n", find_thread(NULL),
207 		this, vecs, vecCount, ancillaryData);
208 
209 	return B_OK;
210 }
211 
212 
213 ssize_t
214 L2capEndpoint::Receive(const iovec *vecs, size_t vecCount,
215 	ancillary_data_container **_ancillaryData, struct sockaddr *_address,
216 	socklen_t *_addressLength)
217 {
218 	debugf("[%ld] %p->L2capEndpoint::Receive(%p, %ld)\n", find_thread(NULL),
219 		this, vecs, vecCount);
220 
221 
222 	return B_OK;
223 }
224 
225 
226 ssize_t
227 L2capEndpoint::ReadData(size_t numBytes, uint32 flags, net_buffer** _buffer)
228 {
229 
230 	return gStackModule->fifo_dequeue_buffer(&fReceivingFifo, flags, B_INFINITE_TIMEOUT, _buffer);
231 
232 }
233 
234 
235 ssize_t
236 L2capEndpoint::Sendable()
237 {
238 	debugf("[%ld] %p->L2capEndpoint::Sendable()\n", find_thread(NULL), this);
239 
240 	return 0;
241 }
242 
243 
244 ssize_t
245 L2capEndpoint::Receivable()
246 {
247 	debugf("[%ld] %p->L2capEndpoint::Receivable()\n", find_thread(NULL), this);
248 
249 	return 0;
250 }
251 
252 
253 L2capEndpoint*
254 L2capEndpoint::ForPsm(uint16 psm)
255 {
256 
257 	L2capEndpoint*	endpoint;
258 
259 	DoublyLinkedList<L2capEndpoint>::Iterator iterator = EndpointList.GetIterator();
260 
261 	while (iterator.HasNext()) {
262 
263 		endpoint = iterator.Next();
264 		if (((struct sockaddr_l2cap*)&endpoint->socket->address)->l2cap_psm == psm
265 			&& endpoint->fState == LISTEN) {
266 			// TODO endpoint ocupied, lock it! define a channel for it
267 			return endpoint;
268 		}
269 	}
270 
271 	return NULL;
272 }
273 
274 
275 void
276 L2capEndpoint::BindToChannel(L2capChannel* channel)
277 {
278 
279 	this->channel = channel;
280 	channel->configuration = &configuration;
281 
282 }
283