📄 tcp.c
字号:
} if (signal_pending(current)) { err = -ERESTARTSYS; goto do_interrupted; } tcp_push_pending_frames(sk, tp); wait_for_tcp_memory(sk); /* If SACK's were formed or PMTU events happened, * we must find out about it. */ mss_now = tcp_current_mss(sk); continue; } seglen -= copy; /* Prepare control bits for TCP header creation engine. */ TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | ((PSH_NEEDED || psh) ? TCPCB_FLAG_PSH : 0)); TCP_SKB_CB(skb)->sacked = 0; if (flags & MSG_OOB) { TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_URG; TCP_SKB_CB(skb)->urg_ptr = copy; } else TCP_SKB_CB(skb)->urg_ptr = 0; /* TCP data bytes are SKB_PUT() on top, later * TCP+IP+DEV headers are SKB_PUSH()'d beneath. * Reserve header space and checksum the data. */ skb_reserve(skb, MAX_HEADER + sk->prot->max_header); skb->csum = csum_and_copy_from_user(from, skb_put(skb, copy), copy, 0, &err); if (err) goto do_fault; from += copy; copied += copy; TCP_SKB_CB(skb)->seq = tp->write_seq; TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + copy; /* This advances tp->write_seq for us. */ tcp_send_skb(sk, skb, queue_it); } } sk->err = 0; err = copied; goto out;do_sock_err: if(copied) err = copied; else err = sock_error(sk); goto out;do_shutdown: if(copied) err = copied; else { if (!(flags&MSG_NOSIGNAL)) send_sig(SIGPIPE, current, 0); err = -EPIPE; } goto out;do_interrupted: if(copied) err = copied; goto out;do_fault: kfree_skb(skb);do_fault2: err = -EFAULT;out: tcp_push_pending_frames(sk, tp); release_sock(sk); return err;}#undef PSH_NEEDED/* * Send an ack if one is backlogged at this point. Ought to merge * this with tcp_send_ack(). * This is called for delayed acks also. */void tcp_read_wakeup(struct sock *sk){ /* If we're closed, don't send an ack, or we'll get a RST * from the closed destination. */ if (sk->state != TCP_CLOSE) tcp_send_ack(sk);}/* * Handle reading urgent data. BSD has very simple semantics for * this, no blocking and very strange errors 8) */static int tcp_recv_urg(struct sock * sk, int nonblock, struct msghdr *msg, int len, int flags, int *addr_len){ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); /* No URG data to read. */ if (sk->urginline || !tp->urg_data || tp->urg_data == URG_READ) return -EINVAL; /* Yes this is right ! */ if (sk->err) return sock_error(sk); if (sk->done) return -ENOTCONN; if (sk->state == TCP_CLOSE || (sk->shutdown & RCV_SHUTDOWN)) { sk->done = 1; return 0; } lock_sock(sk); if (tp->urg_data & URG_VALID) { int err = 0; char c = tp->urg_data; if (!(flags & MSG_PEEK)) tp->urg_data = URG_READ; if(msg->msg_name) tp->af_specific->addr2sockaddr(sk, (struct sockaddr *) msg->msg_name); if(addr_len) *addr_len = tp->af_specific->sockaddr_len; /* Read urgent data. */ msg->msg_flags|=MSG_OOB; release_sock(sk); if(len>0) { err = memcpy_toiovec(msg->msg_iov, &c, 1); /* N.B. already set above ... */ msg->msg_flags|=MSG_OOB; } else msg->msg_flags|=MSG_TRUNC; /* N.B. Is this right?? If len == 0 we didn't read any data */ return err ? -EFAULT : 1; } release_sock(sk); /* Fixed the recv(..., MSG_OOB) behaviour. BSD docs and * the available implementations agree in this case: * this call should never block, independent of the * blocking state of the socket. * Mike <pall@rz.uni-karlsruhe.de> */ return -EAGAIN;}/* * Release a skb if it is no longer needed. This routine * must be called with interrupts disabled or with the * socket locked so that the sk_buff queue operation is ok. */static inline void tcp_eat_skb(struct sock *sk, struct sk_buff * skb){ __skb_unlink(skb, &sk->receive_queue); kfree_skb(skb);}/* Clean up the receive buffer for full frames taken by the user, * then send an ACK if necessary. COPIED is the number of bytes * tcp_recvmsg has given to the user so far, it speeds up the * calculation of whether or not we must ACK for the sake of * a window update. */static void cleanup_rbuf(struct sock *sk, int copied){ struct sk_buff *skb; /* NOTE! The socket must be locked, so that we don't get * a messed-up receive queue. */ while ((skb=skb_peek(&sk->receive_queue)) != NULL) { if (!skb->used || atomic_read(&skb->users) > 1) break; tcp_eat_skb(sk, skb); } /* We send an ACK if we can now advertise a non-zero window * which has been raised "significantly". */ if(copied > 0) { struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); __u32 rcv_window_now = tcp_receive_window(tp); __u32 new_window = __tcp_select_window(sk); /* We won't be raising the window any further than * the window-clamp allows. Our window selection * also keeps things a nice multiple of MSS. These * checks are necessary to prevent spurious ACKs * which don't advertize a larger window. */ if((new_window && (new_window >= rcv_window_now * 2)) && ((rcv_window_now + tp->mss_cache) <= tp->window_clamp)) tcp_read_wakeup(sk); }}/* * This routine copies from a sock struct into the user buffer. */int tcp_recvmsg(struct sock *sk, struct msghdr *msg, int len, int nonblock, int flags, int *addr_len){ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); struct wait_queue wait = { current, NULL }; int copied = 0; u32 peek_seq; volatile u32 *seq; /* So gcc doesn't overoptimise */ unsigned long used; int err = 0; int target = 1; /* Read at least this many bytes */ if (sk->err) return sock_error(sk); if (sk->state == TCP_LISTEN) return -ENOTCONN; /* Urgent data needs to be handled specially. */ if (flags & MSG_OOB) return tcp_recv_urg(sk, nonblock, msg, len, flags, addr_len); /* Copying sequence to update. This is volatile to handle * the multi-reader case neatly (memcpy_to/fromfs might be * inline and thus not flush cached variables otherwise). */ peek_seq = tp->copied_seq; seq = &tp->copied_seq; if (flags & MSG_PEEK) seq = &peek_seq; /* Handle the POSIX bogosity MSG_WAITALL. */ if (flags & MSG_WAITALL) target=len; add_wait_queue(sk->sleep, &wait); lock_sock(sk); /* * BUG BUG BUG * This violates 1003.1g compliance. We must wait for * data to exist even if we read none! */ while (len > 0) { struct sk_buff * skb; u32 offset; /* Are we at urgent data? Stop if we have read anything. */ if (copied && tp->urg_data && tp->urg_seq == *seq) break; /* We need to check signals first, to get correct SIGURG * handling. FIXME: Need to check this doesnt impact 1003.1g * and move it down to the bottom of the loop */ if (signal_pending(current)) { if (copied) break; copied = -ERESTARTSYS; if (nonblock) copied = -EAGAIN; break; } /* Next get a buffer. */ current->state = TASK_INTERRUPTIBLE; skb = skb_peek(&sk->receive_queue); do { if (!skb) break; /* Now that we have two receive queues this * shouldn't happen. */ if (before(*seq, TCP_SKB_CB(skb)->seq)) { printk(KERN_INFO "recvmsg bug: copied %X seq %X\n", *seq, TCP_SKB_CB(skb)->seq); break; } offset = *seq - TCP_SKB_CB(skb)->seq; if (skb->h.th->syn) offset--; if (offset < skb->len) goto found_ok_skb; if (skb->h.th->fin) goto found_fin_ok; if (!(flags & MSG_PEEK)) skb->used = 1; skb = skb->next; } while (skb != (struct sk_buff *)&sk->receive_queue); if (copied >= target) break; /* These three lines and clause if (sk->state == TCP_CLOSE) are unlikely to be correct, if target > 1. I DO NOT FIX IT, because I have no idea, what POSIX prescribes to make here. Probably, it really wants to lose data 8), if not all target is received. --ANK */ if (sk->err && !(flags&MSG_PEEK)) { copied = sock_error(sk); break; } if (sk->shutdown & RCV_SHUTDOWN) { sk->done = 1; break; } if (sk->state == TCP_CLOSE) { if (!sk->done) { sk->done = 1; break; } copied = -ENOTCONN; break; } if (nonblock) { copied = -EAGAIN; break; } cleanup_rbuf(sk, copied); release_sock(sk); sk->socket->flags |= SO_WAITDATA; schedule(); sk->socket->flags &= ~SO_WAITDATA; lock_sock(sk); continue; found_ok_skb: /* Lock the buffer. We can be fairly relaxed as * an interrupt will never steal a buffer we are * using unless I've missed something serious in * tcp_data. */ atomic_inc(&skb->users); /* Ok so how much can we use? */ used = skb->len - offset; if (len < used) used = len; /* Do we have urgent data here? */ if (tp->urg_data) { u32 urg_offset = tp->urg_seq - *seq; if (urg_offset < used) { if (!urg_offset) { if (!sk->urginline) { ++*seq; offset++; used--; } } else used = urg_offset; } } /* Copy it - We _MUST_ update *seq first so that we * don't ever double read when we have dual readers */ *seq += used; /* This memcpy_toiovec can sleep. If it sleeps and we * do a second read it relies on the skb->users to avoid * a crash when cleanup_rbuf() gets called. */ err = memcpy_toiovec(msg->msg_iov, ((unsigned char *)skb->h.th) + skb->h.th->doff*4 + offset, used); if (err) { /* Exception. Bailout! */ atomic_dec(&skb->users); copied = -EFAULT; break; } copied += used; len -= used; /* We now will not sleep again until we are finished * with skb. Sorry if you are doing the SMP port * but you'll just have to fix it neatly ;) */ atomic_dec(&skb->users); if (after(tp->copied_seq,tp->urg_seq)) tp->urg_data = 0; if (used + offset < skb->len) continue; /* Process the FIN. We may also need to handle PSH * here and make it break out of MSG_WAITALL. */ if (skb->h.th->fin) goto found_fin_ok; if (flags & MSG_PEEK) continue; skb->used = 1; if (atomic_read(&skb->users) == 1) tcp_eat_skb(sk, skb); continue; found_fin_ok: ++*seq; if (flags & MSG_PEEK) break; /* All is done. */ skb->used = 1; sk->shutdown |= RCV_SHUTDOWN; break; } if(copied >= 0 && msg->msg_name) { tp->af_specific->addr2sockaddr(sk, (struct sockaddr *) msg->msg_name); if(addr_len) *addr_len = tp->af_specific->sockaddr_len; } remove_wait_queue(sk->sleep, &wait); current->state = TASK_RUNNING; /* Clean up data we have read: This will do ACK frames. */ cleanup_rbuf(sk, copied); release_sock(sk); return copied;}/* * Check whether to renew the timer. */static inline void tcp_check_fin_timer(struct sock *sk){ if (sk->state == TCP_FIN_WAIT2 && !sk->timer.prev) tcp_reset_msl_timer(sk, TIME_CLOSE, sysctl_tcp_fin_timeout);}/* * State processing on a close. This implements the state shift for * sending our FIN frame. Note that we only send a FIN for some * states. A shutdown() may have already sent the FIN, or we may be * closed. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -