aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/proto.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@mandriva.com>2005-08-13 19:35:17 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 18:59:34 -0400
commit531669a0a9041d60d13920973ef8aa4f743c14a0 (patch)
treee1225d8e4e3ef708117729f264e6fad14df0c283 /net/dccp/proto.c
parent7690af3fff7633e40b1b9950eb8489129251d074 (diff)
[DCCP]: Rewrite dccp_sendmsg to be more like UDP
Based on discussions with Nishida-san. Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp/proto.c')
-rw-r--r--net/dccp/proto.c214
1 files changed, 59 insertions, 155 deletions
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 46dd489f66cf..ed0bf58c8ae0 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -214,197 +214,101 @@ out_discard:
214 goto out_release; 214 goto out_release;
215} 215}
216 216
217EXPORT_SYMBOL(dccp_sendmsg);
218
219int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, 217int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
220 size_t len, int nonblock, int flags, int *addr_len) 218 size_t len, int nonblock, int flags, int *addr_len)
221{ 219{
222 const struct dccp_hdr *dh; 220 const struct dccp_hdr *dh;
223 int copied = 0;
224 unsigned long used;
225 int err;
226 int target; /* Read at least this many bytes */
227 long timeo; 221 long timeo;
228 222
229 lock_sock(sk); 223 lock_sock(sk);
230 224
231 err = -ENOTCONN; 225 if (sk->sk_state == DCCP_LISTEN) {
232 if (sk->sk_state == DCCP_LISTEN) 226 len = -ENOTCONN;
233 goto out; 227 goto out;
234
235 timeo = sock_rcvtimeo(sk, nonblock);
236
237 /* Urgent data needs to be handled specially. */
238 if (flags & MSG_OOB)
239 goto recv_urg;
240
241 /* FIXME */
242#if 0
243 seq = &tp->copied_seq;
244 if (flags & MSG_PEEK) {
245 peek_seq = tp->copied_seq;
246 seq = &peek_seq;
247 } 228 }
248#endif
249 229
250 target = sock_rcvlowat(sk, flags & MSG_WAITALL, len); 230 timeo = sock_rcvtimeo(sk, nonblock);
251 231
252 do { 232 do {
253 struct sk_buff *skb; 233 struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
254 u32 offset;
255 234
256 /* FIXME */ 235 if (skb == NULL)
257#if 0 236 goto verify_sock_status;
258 /*
259 * Are we at urgent data? Stop if we have read anything or
260 * have SIGURG pending.
261 */
262 if (tp->urg_data && tp->urg_seq == *seq) {
263 if (copied)
264 break;
265 if (signal_pending(current)) {
266 copied = timeo ? sock_intr_errno(timeo) :
267 -EAGAIN;
268 break;
269 }
270 }
271#endif
272 237
273 /* Next get a buffer. */ 238 dh = dccp_hdr(skb);
274
275 skb = skb_peek(&sk->sk_receive_queue);
276 do {
277 if (!skb)
278 break;
279 239
280 offset = 0; 240 if (dh->dccph_type == DCCP_PKT_DATA ||
281 dh = dccp_hdr(skb); 241 dh->dccph_type == DCCP_PKT_DATAACK)
242 goto found_ok_skb;
282 243
283 if (dh->dccph_type == DCCP_PKT_DATA || 244 if (dh->dccph_type == DCCP_PKT_RESET ||
284 dh->dccph_type == DCCP_PKT_DATAACK) 245 dh->dccph_type == DCCP_PKT_CLOSE) {
285 goto found_ok_skb; 246 dccp_pr_debug("found fin ok!\n");
286 247 len = 0;
287 if (dh->dccph_type == DCCP_PKT_RESET || 248 goto found_fin_ok;
288 dh->dccph_type == DCCP_PKT_CLOSE) { 249 }
289 dccp_pr_debug("found fin ok!\n"); 250 dccp_pr_debug("packet_type=%s\n",
290 goto found_fin_ok; 251 dccp_packet_name(dh->dccph_type));
291 } 252 sk_eat_skb(sk, skb);
292 dccp_pr_debug("packet_type=%s\n", 253verify_sock_status:
293 dccp_packet_name(dh->dccph_type)); 254 if (sock_flag(sk, SOCK_DONE)) {
294 BUG_TRAP(flags & MSG_PEEK); 255 len = 0;
295 skb = skb->next;
296 } while (skb != (struct sk_buff *)&sk->sk_receive_queue);
297
298 /* Well, if we have backlog, try to process it now yet. */
299 if (copied >= target && !sk->sk_backlog.tail)
300 break; 256 break;
257 }
301 258
302 if (copied) { 259 if (sk->sk_err) {
303 if (sk->sk_err || 260 len = sock_error(sk);
304 sk->sk_state == DCCP_CLOSED || 261 break;
305 (sk->sk_shutdown & RCV_SHUTDOWN) || 262 }
306 !timeo ||
307 signal_pending(current) ||
308 (flags & MSG_PEEK))
309 break;
310 } else {
311 if (sock_flag(sk, SOCK_DONE))
312 break;
313
314 if (sk->sk_err) {
315 copied = sock_error(sk);
316 break;
317 }
318
319 if (sk->sk_shutdown & RCV_SHUTDOWN)
320 break;
321
322 if (sk->sk_state == DCCP_CLOSED) {
323 if (!sock_flag(sk, SOCK_DONE)) {
324 /* This occurs when user tries to read
325 * from never connected socket.
326 */
327 copied = -ENOTCONN;
328 break;
329 }
330 break;
331 }
332 263
333 if (!timeo) { 264 if (sk->sk_shutdown & RCV_SHUTDOWN) {
334 copied = -EAGAIN; 265 len = 0;
335 break; 266 break;
336 } 267 }
337 268
338 if (signal_pending(current)) { 269 if (sk->sk_state == DCCP_CLOSED) {
339 copied = sock_intr_errno(timeo); 270 if (!sock_flag(sk, SOCK_DONE)) {
271 /* This occurs when user tries to read
272 * from never connected socket.
273 */
274 len = -ENOTCONN;
340 break; 275 break;
341 } 276 }
277 len = 0;
278 break;
342 } 279 }
343 280
344 /* FIXME: cleanup_rbuf(sk, copied); */ 281 if (!timeo) {
282 len = -EAGAIN;
283 break;
284 }
345 285
346 if (copied >= target) { 286 if (signal_pending(current)) {
347 /* Do not sleep, just process backlog. */ 287 len = sock_intr_errno(timeo);
348 release_sock(sk); 288 break;
349 lock_sock(sk); 289 }
350 } else
351 sk_wait_data(sk, &timeo);
352 290
291 sk_wait_data(sk, &timeo);
353 continue; 292 continue;
354
355 found_ok_skb: 293 found_ok_skb:
356 /* Ok so how much can we use? */ 294 if (len > skb->len)
357 used = skb->len - offset; 295 len = skb->len;
358 if (len < used) 296 else if (len < skb->len)
359 used = len; 297 msg->msg_flags |= MSG_TRUNC;
360 298
361 if (!(flags & MSG_TRUNC)) { 299 if (skb_copy_datagram_iovec(skb, 0, msg->msg_iov, len)) {
362 err = skb_copy_datagram_iovec(skb, offset, 300 /* Exception. Bailout! */
363 msg->msg_iov, used); 301 len = -EFAULT;
364 if (err) { 302 break;
365 /* Exception. Bailout! */
366 if (!copied)
367 copied = -EFAULT;
368 break;
369 }
370 } 303 }
371
372 copied += used;
373 len -= used;
374
375 /* FIXME: tcp_rcv_space_adjust(sk); */
376
377//skip_copy:
378 if (used + offset < skb->len)
379 continue;
380
381 if (!(flags & MSG_PEEK))
382 sk_eat_skb(sk, skb);
383 continue;
384 found_fin_ok: 304 found_fin_ok:
385 if (!(flags & MSG_PEEK)) 305 if (!(flags & MSG_PEEK))
386 sk_eat_skb(sk, skb); 306 sk_eat_skb(sk, skb);
387 break; 307 break;
388 308 } while (1);
389 } while (len > 0);
390
391 /* According to UNIX98, msg_name/msg_namelen are ignored
392 * on connected socket. I was just happy when found this 8) --ANK
393 */
394
395 /* Clean up data we have read: This will do ACK frames. */
396 /* FIXME: cleanup_rbuf(sk, copied); */
397
398 release_sock(sk);
399 return copied;
400
401out: 309out:
402 release_sock(sk); 310 release_sock(sk);
403 return err; 311 return len;
404
405recv_urg:
406 /* FIXME: err = tcp_recv_urg(sk, timeo, msg, len, flags, addr_len); */
407 goto out;
408} 312}
409 313
410static int inet_dccp_listen(struct socket *sock, int backlog) 314static int inet_dccp_listen(struct socket *sock, int backlog)