Chinaunix首页 | 论坛 | 博客
  • 博客访问: 154487
  • 博文数量: 41
  • 博客积分: 2500
  • 博客等级: 少校
  • 技术积分: 425
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-14 10:16
文章分类
文章存档

2011年(1)

2010年(5)

2009年(35)

我的朋友

分类: LINUX

2009-10-09 10:41:53

  /*

        * We also need to worry about the window.

       * If window < 1/2 the maximum window we've seen from this

       *   host, don't use it.  This is sender side

       *   silly window prevention, as specified in RFC1122.

       *   (Note that this is different than earlier versions of

       *   SWS prevention, e.g. RFC813.).  What we actually do is

        *   use the whole MSS.  Since the results in the right

        *   edge of the packet being outside the window, it will

        *   be queued for later rather than sent.

        */

 

              copy = sk->window_seq - sk->write_seq;

              if (copy <= 0 || copy < (sk->max_window >> 1) || copy > sk->mss)

                     copy = sk->mss;

              if (copy > len)

                     copy = len;

 

       /*

        *    We should really check the window here also.

        */

        

              send_tmp = NULL;

              if (copy < sk->mss && !(flags & MSG_OOB))

              {

                     /*

                      *    We will release the socket in case we sleep here.

                      */

                     release_sock(sk);

                     /*

                      *    NB: following must be mtu, because mss can be increased.

                      *    mss is always <= mtu

                      */

                     skb = prot->wmalloc(sk, sk->mtu + 128 + prot->max_header, 0, GFP_KERNEL);

                     sk->inuse = 1;

                     send_tmp = skb;

              }

              else

              {

                     /*

                      *    We will release the socket in case we sleep here.

                      */

                     release_sock(sk);

                     skb = prot->wmalloc(sk, copy + prot->max_header , 0, GFP_KERNEL);

                    sk->inuse = 1;

              }

 

              /*

               *    If we didn't get any memory, we need to sleep.

               */

 

              if (skb == NULL)

              {

                     sk->socket->flags |= SO_NOSPACE;

                     if (nonblock)

                     {

                            release_sock(sk);

                            if (copied)

                                   return(copied);

                            return(-EAGAIN);

                     }

 

                     /*

                      *    FIXME: here is another race condition.

                      */

 

                     tmp = sk->wmem_alloc;

                     release_sock(sk);

                     cli();

                     /*

                      *    Again we will try to avoid it.

                      */

                     if (tmp <= sk->wmem_alloc &&

                              (sk->state == TCP_ESTABLISHED||sk->state == TCP_CLOSE_WAIT)

                            && sk->err == 0)

                     {

                            sk->socket->flags &= ~SO_NOSPACE;

                            interruptible_sleep_on(sk->sleep);

                            if (current->signal & ~current->blocked)

                            {

                                   sti();

                                   if (copied)

                                          return(copied);

                                   return(-ERESTARTSYS);

                            }

                     }

                     sk->inuse = 1;

                     sti();

                     continue;

              }

 

              skb->len = 0;

              skb->sk = sk;

              skb->free = 0;

              skb->localroute = sk->localroute|(flags&MSG_DONTROUTE);

      

              buff = skb->data;

      

              /*

               * FIXME: we need to optimize this.

               * Perhaps some hints here would be good.

               */

             

              tmp = prot->build_header(skb, sk->saddr, sk->daddr, &dev,

                             IPPROTO_TCP, sk->opt, skb->mem_len,sk->ip_tos,sk->ip_ttl);

              if (tmp < 0 )

              {

                     prot->wfree(sk, skb->mem_addr, skb->mem_len);

                     release_sock(sk);

                     if (copied)

                            return(copied);

                     return(tmp);

              }

              skb->len += tmp;

              skb->dev = dev;

              buff += tmp;

              skb->h.th =(struct tcphdr *) buff;

              tmp = tcp_build_header((struct tcphdr *)buff, sk, len-copy);

              if (tmp < 0)

              {

                     prot->wfree(sk, skb->mem_addr, skb->mem_len);

                     release_sock(sk);

                     if (copied)

                            return(copied);

                     return(tmp);

              }

 

              if (flags & MSG_OOB)

              {

                     ((struct tcphdr *)buff)->urg = 1;

                     ((struct tcphdr *)buff)->urg_ptr = ntohs(copy);

              }

              skb->len += tmp;

              memcpy_fromfs(buff+tmp, from, copy);

 

              from += copy;

              copied += copy;

              len -= copy;

              skb->len += copy;

              skb->free = 0;

              sk->write_seq += copy;

      

              if (send_tmp != NULL && sk->packets_out)

              {

                     tcp_enqueue_partial(send_tmp, sk);

                     continue;

              }

              tcp_send_skb(sk, skb);

       }

       sk->err = 0;

 

/*

 *    Nagle's rule. Turn Nagle off with TCP_NODELAY for highly

 *    interactive fast network servers. It's meant to be on and

 *    it really improves the throughput though not the echo time

 *    on my slow slip link - Alan

 */

 

/*

 *    Avoid possible race on send_tmp - c/o Johannes Stille

 */

 

       if(sk->partial && ((!sk->packets_out)

     /* If not nagling we can send on the before case too.. */

             || (sk->nonagle && before(sk->write_seq , sk->window_seq))

          ))

             tcp_send_partial(sk);

 

       release_sock(sk);

       return(copied);

}

阅读(1607) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~