diff options
author | Arnaldo Carvalho de Melo <acme@mandriva.com> | 2005-08-13 19:35:17 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 18:59:34 -0400 |
commit | 531669a0a9041d60d13920973ef8aa4f743c14a0 (patch) | |
tree | e1225d8e4e3ef708117729f264e6fad14df0c283 /net | |
parent | 7690af3fff7633e40b1b9950eb8489129251d074 (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')
-rw-r--r-- | net/dccp/proto.c | 214 |
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 | ||
217 | EXPORT_SYMBOL(dccp_sendmsg); | ||
218 | |||
219 | int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | 217 | int 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", | 253 | verify_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 | |||
401 | out: | 309 | out: |
402 | release_sock(sk); | 310 | release_sock(sk); |
403 | return err; | 311 | return len; |
404 | |||
405 | recv_urg: | ||
406 | /* FIXME: err = tcp_recv_urg(sk, timeo, msg, len, flags, addr_len); */ | ||
407 | goto out; | ||
408 | } | 312 | } |
409 | 313 | ||
410 | static int inet_dccp_listen(struct socket *sock, int backlog) | 314 | static int inet_dccp_listen(struct socket *sock, int backlog) |