/[lwip]/lwip/src/core/tcp.c
ViewVC logotype

Diff of /lwip/src/core/tcp.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.48 by christiaans, Tue Dec 7 08:16:27 2004 UTC revision 1.49 by christiaans, Fri Nov 25 12:03:38 2005 UTC
# Line 237  err_t Line 237  err_t
237  tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)  tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
238  {  {
239    struct tcp_pcb *cpcb;    struct tcp_pcb *cpcb;
 #if SO_REUSE  
   int reuse_port_all_set = 1;  
 #endif /* SO_REUSE */  
240    
241    if (port == 0) {    if (port == 0) {
242      port = tcp_new_port();      port = tcp_new_port();
243    }    }
 #if SO_REUSE == 0  
244    /* Check if the address already is in use. */    /* Check if the address already is in use. */
245    for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs;    for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs;
246        cpcb != NULL; cpcb = cpcb->next) {        cpcb != NULL; cpcb = cpcb->next) {
# Line 266  tcp_bind(struct tcp_pcb *pcb, struct ip_ Line 262  tcp_bind(struct tcp_pcb *pcb, struct ip_
262        }        }
263      }      }
264    }    }
 #else /* SO_REUSE */  
   /* Search through list of PCB's in LISTEN state.  
       
   If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP  
   or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to  
   the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.  
   But no two PCB's bound to same local port and same local address is valid.  
     
   If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then  
   all PCB's must have the SOF_REUSEPORT option set.  
     
   When the two options aren't set and specified port is already bound, ERR_USE is returned saying that  
   address is already in use. */  
   for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; cpcb != NULL; cpcb = cpcb->next) {  
     if(cpcb->local_port == port) {  
       if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {  
         if(pcb->so_options & SOF_REUSEPORT) {  
           LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT set and same address.\n"));  
           reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));  
         }  
         else {  
           LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT not set and same address.\n"));  
           return ERR_USE;  
         }  
       }  
       else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||  
               (!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {  
         if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {  
           LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));  
           return ERR_USE;  
         }        
         else {  
           LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));  
         }      
       }  
     }  
   }  
   
   /* Search through list of PCB's in a state in which they can accept or send data. Same decription as for  
      PCB's in state LISTEN applies to this PCB's regarding the options SOF_REUSEADDR and SOF_REUSEPORT. */  
   for(cpcb = tcp_active_pcbs; cpcb != NULL; cpcb = cpcb->next) {  
     if(cpcb->local_port == port) {  
       if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {  
         if(pcb->so_options & SOF_REUSEPORT) {  
           LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT set and same address.\n"));  
           reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));  
         }  
         else {  
           LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT not set and same address.\n"));  
           return ERR_USE;  
         }  
       }  
       else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||  
               (!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {  
         if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {  
           LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));  
           return ERR_USE;  
         }    
         else {  
           LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));  
         }          
       }  
     }  
   }  
   
   /* Search through list of PCB's in TIME_WAIT state. If SO_REUSEADDR is set a bound combination [IP, port}  
      can be rebound. The same applies when SOF_REUSEPORT is set.  
       
      If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then  
      all PCB's must have the SOF_REUSEPORT option set.  
       
      When the two options aren't set and specified port is already bound, ERR_USE is returned saying that  
      address is already in use. */  
   for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) {  
     if(cpcb->local_port == port) {  
       if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {  
         if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {  
           LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT or SO_REUSEADDR not set and same address.\n"));  
           return ERR_USE;  
         }  
         else if(pcb->so_options & SOF_REUSEPORT) {  
           LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT set and same address.\n"));  
           reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));  
         }  
       }  
     }  
   }  
   
   /* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then  
      {IP, port} can't be reused. */  
   if(!reuse_port_all_set) {  
     LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: not all sockets have SO_REUSEPORT set.\n"));  
     return ERR_USE;  
   }  
 #endif /* SO_REUSE */  
265    
266    if (!ip_addr_isany(ipaddr)) {    if (!ip_addr_isany(ipaddr)) {
267      pcb->local_ip = *ipaddr;      pcb->local_ip = *ipaddr;
268    }    }
269    pcb->local_port = port;    pcb->local_port = port;
270    LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %u\n", port));    LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port));
271    return ERR_OK;    return ERR_OK;
272  }  }
273  #if LWIP_CALLBACK_API  #if LWIP_CALLBACK_API
# Line 456  tcp_recved(struct tcp_pcb *pcb, u16_t le Line 357  tcp_recved(struct tcp_pcb *pcb, u16_t le
357      tcp_ack_now(pcb);      tcp_ack_now(pcb);
358    }    }
359    
360    LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %u bytes, wnd %u (%u).\n",    LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n",
361           len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));           len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
362  }  }
363    
# Line 510  tcp_connect(struct tcp_pcb *pcb, struct Line 411  tcp_connect(struct tcp_pcb *pcb, struct
411    err_t ret;    err_t ret;
412    u32_t iss;    u32_t iss;
413    
414    LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %u\n", port));    LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
415    if (ipaddr != NULL) {    if (ipaddr != NULL) {
416      pcb->remote_ip = *ipaddr;      pcb->remote_ip = *ipaddr;
417    } else {    } else {
# Line 592  tcp_slowtmr(void) Line 493  tcp_slowtmr(void)
493        if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {        if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
494    
495          /* Time for a retransmission. */          /* Time for a retransmission. */
496          LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %u pcb->rto %u\n",          LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"U16_F" pcb->rto %"U16_F"\n",
497            pcb->rtime, pcb->rto));            pcb->rtime, pcb->rto));
498    
499          /* Double retransmission time-out unless we are trying to          /* Double retransmission time-out unless we are trying to
# Line 607  tcp_slowtmr(void) Line 508  tcp_slowtmr(void)
508            pcb->ssthresh = pcb->mss * 2;            pcb->ssthresh = pcb->mss * 2;
509          }          }
510          pcb->cwnd = pcb->mss;          pcb->cwnd = pcb->mss;
511          LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %u ssthresh %u\n",          LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F" ssthresh %"U16_F"\n",
512                                  pcb->cwnd, pcb->ssthresh));                                  pcb->cwnd, pcb->ssthresh));
513    
514          /* The following needs to be called AFTER cwnd is set to one mss - STJ */          /* The following needs to be called AFTER cwnd is set to one mss - STJ */
# Line 626  tcp_slowtmr(void) Line 527  tcp_slowtmr(void)
527     /* Check if KEEPALIVE should be sent */     /* Check if KEEPALIVE should be sent */
528     if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {     if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
529        if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL)  {        if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL)  {
530           LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %u.%u.%u.%u.\n",           LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n",
531                                   ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),                                   ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
532                                   ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));                                   ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
533    
# Line 814  tcp_seg_copy(struct tcp_seg *seg) Line 715  tcp_seg_copy(struct tcp_seg *seg)
715    if (cseg == NULL) {    if (cseg == NULL) {
716      return NULL;      return NULL;
717    }    }
718    memcpy((char *)cseg, (const char *)seg, sizeof(struct tcp_seg));    memcpy((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg));
719    pbuf_ref(cseg->p);    pbuf_ref(cseg->p);
720    return cseg;    return cseg;
721  }  }
# Line 858  tcp_kill_prio(u8_t prio) Line 759  tcp_kill_prio(u8_t prio)
759      }      }
760    }    }
761    if (inactive != NULL) {    if (inactive != NULL) {
762      LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%ld)\n",      LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n",
763             (void *)inactive, inactivity));             (void *)inactive, inactivity));
764      tcp_abort(inactive);      tcp_abort(inactive);
765    }          }      
# Line 880  tcp_kill_timewait(void) Line 781  tcp_kill_timewait(void)
781      }      }
782    }    }
783    if (inactive != NULL) {    if (inactive != NULL) {
784      LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%ld)\n",      LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n",
785             (void *)inactive, inactivity));             (void *)inactive, inactivity));
786      tcp_abort(inactive);      tcp_abort(inactive);
787    }          }      
# Line 1112  tcp_debug_print(struct tcp_hdr *tcphdr) Line 1013  tcp_debug_print(struct tcp_hdr *tcphdr)
1013  {  {
1014    LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));    LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
1015    LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));    LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
1016    LWIP_DEBUGF(TCP_DEBUG, ("|    %5u      |    %5u      | (src port, dest port)\n",    LWIP_DEBUGF(TCP_DEBUG, ("|    %5"U16_F"      |    %5"U16_F"      | (src port, dest port)\n",
1017           ntohs(tcphdr->src), ntohs(tcphdr->dest)));           ntohs(tcphdr->src), ntohs(tcphdr->dest)));
1018    LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));    LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
1019    LWIP_DEBUGF(TCP_DEBUG, ("|           %010lu          | (seq no)\n",    LWIP_DEBUGF(TCP_DEBUG, ("|           %010"U32_F"          | (seq no)\n",
1020            ntohl(tcphdr->seqno)));            ntohl(tcphdr->seqno)));
1021    LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));    LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
1022    LWIP_DEBUGF(TCP_DEBUG, ("|           %010lu          | (ack no)\n",    LWIP_DEBUGF(TCP_DEBUG, ("|           %010"U32_F"          | (ack no)\n",
1023           ntohl(tcphdr->ackno)));           ntohl(tcphdr->ackno)));
1024    LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));    LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
1025    LWIP_DEBUGF(TCP_DEBUG, ("| %2u |   |%u%u%u%u%u%u|     %5u     | (hdrlen, flags (",    LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" |   |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"|     %5"U16_F"     | (hdrlen, flags (",
1026         TCPH_HDRLEN(tcphdr),         TCPH_HDRLEN(tcphdr),
1027           TCPH_FLAGS(tcphdr) >> 5 & 1,           TCPH_FLAGS(tcphdr) >> 5 & 1,
1028           TCPH_FLAGS(tcphdr) >> 4 & 1,           TCPH_FLAGS(tcphdr) >> 4 & 1,
# Line 1133  tcp_debug_print(struct tcp_hdr *tcphdr) Line 1034  tcp_debug_print(struct tcp_hdr *tcphdr)
1034    tcp_debug_print_flags(TCPH_FLAGS(tcphdr));    tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
1035    LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));    LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
1036    LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));    LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
1037    LWIP_DEBUGF(TCP_DEBUG, ("|    0x%04x     |     %5u     | (chksum, urgp)\n",    LWIP_DEBUGF(TCP_DEBUG, ("|    0x%04"X16_F"     |     %5"U16_F"     | (chksum, urgp)\n",
1038           ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));           ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
1039    LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));    LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
1040  }  }
# Line 1214  tcp_debug_print_pcbs(void) Line 1115  tcp_debug_print_pcbs(void)
1115    struct tcp_pcb *pcb;    struct tcp_pcb *pcb;
1116    LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n"));    LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n"));
1117    for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {    for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
1118      LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ",      LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
1119                         pcb->local_port, pcb->remote_port,                         pcb->local_port, pcb->remote_port,
1120                         pcb->snd_nxt, pcb->rcv_nxt));                         pcb->snd_nxt, pcb->rcv_nxt));
1121      tcp_debug_print_state(pcb->state);      tcp_debug_print_state(pcb->state);
1122    }        }    
1123    LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n"));    LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n"));
1124    for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {    for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
1125      LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ",      LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
1126                         pcb->local_port, pcb->remote_port,                         pcb->local_port, pcb->remote_port,
1127                         pcb->snd_nxt, pcb->rcv_nxt));                         pcb->snd_nxt, pcb->rcv_nxt));
1128      tcp_debug_print_state(pcb->state);      tcp_debug_print_state(pcb->state);
1129    }        }    
1130    LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n"));    LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n"));
1131    for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {    for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
1132      LWIP_DEBUGF(TCP_DEBUG, ("Local port %u, foreign port %u snd_nxt %lu rcv_nxt %lu ",      LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
1133                         pcb->local_port, pcb->remote_port,                         pcb->local_port, pcb->remote_port,
1134                         pcb->snd_nxt, pcb->rcv_nxt));                         pcb->snd_nxt, pcb->rcv_nxt));
1135      tcp_debug_print_state(pcb->state);      tcp_debug_print_state(pcb->state);
1136    }        }    
1137  }  }
1138    
1139  int  s16_t
1140  tcp_pcbs_sane(void)  tcp_pcbs_sane(void)
1141  {  {
1142    struct tcp_pcb *pcb;    struct tcp_pcb *pcb;

Legend:
Removed from v.1.48  
changed lines
  Added in v.1.49

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26