⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 connect.c

📁 用于嵌入式系统的TCP/IP协议栈
💻 C
字号:
/***********************************************************************//*                                                                     *//*   Module:  connect.c                                                *//*   Release: 2001.3                                                   *//*   Version: 2000.0                                                   *//*   Purpose: connect() implementation                                 *//*                                                                     *//*---------------------------------------------------------------------*//*                                                                     *//*               Copyright 1999, Blunk Microsystems                    *//*                      ALL RIGHTS RESERVED                            *//*                                                                     *//*   Licensees have the non-exclusive right to use, modify, or extract *//*   this computer program for software development at a single site.  *//*   This program may be resold or disseminated in executable format   *//*   only. The source code may not be redistributed or resold.         *//*                                                                     *//***********************************************************************/#include "../tcp_ipp.h"#include "../tcp/tcp.h"#include "../ip/ip.h"/***********************************************************************//* Local Function Definitions                                          *//***********************************************************************//***********************************************************************//*    tcp_conn: Actively establish TCP connection with peer            *//*                                                                     *//*       Input: sock = pointer to TCP socket                           *//*                                                                     *//*     Returns: 0 if no errors, else -1 with errno set to error code   *//*                                                                     *//***********************************************************************/static int tcp_conn(SOCKET sock){  int mss;  /*-------------------------------------------------------------------*/  /* Verify socket is not already connected.                           */  /*-------------------------------------------------------------------*/  if (sock->flags & SF_CONNECTED)  {    NetError(sock, EISCONN);    return -1;  }  /*-------------------------------------------------------------------*/  /* Check if a connection is in progress.                             */  /*-------------------------------------------------------------------*/  if (sock->flags & TCPF_SYN)  {    if ((sock->state == SS_SYNSENT) || (sock->state == SS_SYNRCVD))    {      NetError(sock, EINPROGRESS);      return -1;    }    else    {      sock->flags &= ~TCPF_SYN;      NetError(sock, sock->error);      return -1;    }  }  /*-------------------------------------------------------------------*/  /* Allocate socket send buffer.                                      */  /*-------------------------------------------------------------------*/  if (sock->sbuf == NULL)  {    sock->sbuf = tcpGetBuf(sock->sb_size);    if (sock->sbuf == NULL)    {      NetError(sock, ENOBUFS);      return -1;    }  }  /*-------------------------------------------------------------------*/  /* Allocate socket receive buffer.                                   */  /*-------------------------------------------------------------------*/  if (sock->rbuf == NULL)  {    sock->rbuf = tcpGetBuf(sock->rb_size);    if (sock->rbuf == NULL)    {      NetError(sock, ENOBUFS);      return -1;    }  }  /*-------------------------------------------------------------------*/  /* If local port has not been specified, pick a unique port.         */  /*-------------------------------------------------------------------*/  if (sock->local.sin_port == 0)  {    sock->local.sin_port = TcpNextPort();    if (sock->local.sin_port == 0)    {      NetError(sock, EMFILE);      return -1;    }  }  /*-------------------------------------------------------------------*/  /* Else ensure socket's local and remote addresses are unique.       */  /*-------------------------------------------------------------------*/  else  {    SOCKET next;    CircLink *link;    for (link = TcpLruList.next_bck;; link = link->next_bck)    {      /*---------------------------------------------------------------*/      /* Break if TCP socket list end is reached.                      */      /*---------------------------------------------------------------*/      if (link == &TcpLruList)        break;      /*---------------------------------------------------------------*/      /* Error if a different socket has the same addresses.           */      /*---------------------------------------------------------------*/      next = (SOCKET)link;      if ((sock->local.sin_port == next->local.sin_port) &&          (sock->local.sin_addr.s_addr == next->local.sin_addr.s_addr) &&          (sock->remote.sin_port == next->remote.sin_port) &&          (sock->remote.sin_addr.s_addr == next->remote.sin_addr.s_addr))      {        if (next != sock)        {          NetError(sock, EADDRINUSE);          return -1;        }      }    }  }  /*-------------------------------------------------------------------*/  /* Determine our maximum receive segment size.                       */  /*-------------------------------------------------------------------*/  mss = sock->route->ni->mtu - (IPMHLEN + TCPMHLEN);  /*-------------------------------------------------------------------*/  /* Initialization specific to active opens.                          */  /*-------------------------------------------------------------------*/  sock->snd_mss = sock->snd_window = sock->snd_cwnd = mss;  if (mss > (sock->rb_size >> 1))    sock->rcv_mss = sock->rb_size >> 1;  else    sock->rcv_mss = mss;  sock->flags |= TCPF_SYN;  sock->state = SS_SYNSENT;  /*-------------------------------------------------------------------*/  /* Reserve socket for TCP state machine and initiate SYN output.     */  /*-------------------------------------------------------------------*/  ++sock->reserve_cnt;  ++Stats.TcpActiveOpens;  TcpTryOut(sock);  /*-------------------------------------------------------------------*/  /* Start connect() timer to expire after timeout.                    */  /*-------------------------------------------------------------------*/  NetTimerStart(&sock->state_tmr, sock->connect_timeo);  /*-------------------------------------------------------------------*/  /* If non-blocking, return error.                                    */  /*-------------------------------------------------------------------*/  if (sock->flags & SF_NONBLKNG)  {    NetError(sock, EWOULDBLOCK);    return -1;  }  /*-------------------------------------------------------------------*/  /* Wait for event and check for timeout.                             */  /*-------------------------------------------------------------------*/  NetPendEvent(sock, SE_CLOSED | SE_OPENED, WAIT_FOREVER);  if (sock->error)  {    NetError(sock, sock->error);    return -1;  }  /*-------------------------------------------------------------------*/  /* Return 0 for success.                                             */  /*-------------------------------------------------------------------*/  return 0;}/***********************************************************************//* Global Function Definitions                                         *//***********************************************************************//***********************************************************************//*     connect: Attach a remote address to a socket and, for stream    *//*              sockets, actively establish connection with peer       *//*                                                                     *//*      Inputs: s = socket identifier                                  *//*              a = pointer to remote address                          *//*              addrlen = sizeof(struct sockaddr_in)                   *//*                                                                     *//*     Returns: 0 if no errors, else -1 with errno set to error code   *//*                                                                     *//***********************************************************************/int connect(int s, const void *a, int addrlen){  SOCKET sock = &Socks[s - 1];  SockAddr *addr = (SockAddr *)a;  Route *route;  ui16 sin_port;  ui32 s_addr;  int rc = -1;#if OS_PARM_CHECK  /*-------------------------------------------------------------------*/  /* Verify protocol has been initialized.                             */  /*-------------------------------------------------------------------*/  if (!Net.Initialized)  {    NetError(NULL, ENETDOWN);    return -1;  }  /*-------------------------------------------------------------------*/  /* Check for valid socket ID.                                        */  /*-------------------------------------------------------------------*/  if (InvalidHandle(s))  {    NetError(NULL, ENOTSOCK);    return -1;  }  /*-------------------------------------------------------------------*/  /* Verify a is not NULL and addrlen is the appropriate value.        */  /*-------------------------------------------------------------------*/  if (!a || (addrlen != sizeof(struct sockaddr_in)))  {    NetError(sock, EFAULT);    return -1;  }  /*-------------------------------------------------------------------*/  /* Verify the specified address family is AF_INET.                   */  /*-------------------------------------------------------------------*/  if (addr->sin_family != AF_INET)  {    NetError(sock, EPFNOSUPPORT);    return -1;  }  /*-------------------------------------------------------------------*/  /* Verify destination IP address and port number are not zero.       */  /*-------------------------------------------------------------------*/  if ((addr->sin_addr.s_addr == INADDR_ANY) || (addr->sin_port == 0))  {    NetError(sock, EDESTADDRREQ);    return -1;  }#endif  /*-------------------------------------------------------------------*/  /* Gain exclusive socket API access and stack internals access.      */  /*-------------------------------------------------------------------*/  if (semPend(sock->api_access, WAIT_FOREVER))  {    NetError(NULL, ENOTSOCK);    return -1;  }  semPend(Net.IntSem, WAIT_FOREVER);  /*-------------------------------------------------------------------*/  /* Verify an acceptable route exists and cache it.                   */  /*-------------------------------------------------------------------*/  route = RtSearch(addr->sin_addr.s_addr);  if ((route == NULL) ||      ((sock->flags & SF_DONTROUTE) && (route->flags & RT_GATEWAY)))  {    sock->flags &= ~SF_CONNECTED;    NetError(sock, ENETUNREACH);    goto conn_exit;  }  sock->route = route;  /*-------------------------------------------------------------------*/  /* Save original local address and port, restored if UDP error.      */  /*-------------------------------------------------------------------*/  s_addr = sock->local.sin_addr.s_addr;  sin_port = sock->local.sin_port;  /*-------------------------------------------------------------------*/  /* Assign local IP address if wild card IP address used.             */  /*-------------------------------------------------------------------*/  if (sock->local.sin_addr.s_addr == INADDR_ANY)    sock->local.sin_addr.s_addr = route->ni->ip_addr;  /*-------------------------------------------------------------------*/  /* Assign specified remote port number and IP address to socket.     */  /*-------------------------------------------------------------------*/  sock->remote.sin_port = addr->sin_port;  sock->remote.sin_addr = addr->sin_addr;  /*-------------------------------------------------------------------*/  /* UDP socket processing.                                            */  /*-------------------------------------------------------------------*/  if (sock->type == SOCK_DGRAM)  {    /*-----------------------------------------------------------------*/    /* Verify destination IP address is an available address.          */    /*-----------------------------------------------------------------*/    if ((route->flags & RT_BRDCST) && !(sock->flags & SF_BROADCAST))      NetError(sock, EACCES);    /*-----------------------------------------------------------------*/    /* Else perform UDP connection.                                    */    /*-----------------------------------------------------------------*/    else      rc = UdpConnect(sock);    /*-----------------------------------------------------------------*/    /* UDP error clears connection and restores local addresses.       */    /*-----------------------------------------------------------------*/    if (rc)    {      sock->flags &= ~SF_CONNECTED;      sock->local.sin_addr.s_addr = s_addr;      sock->local.sin_port = sin_port;    }  }  /*-------------------------------------------------------------------*/  /* TCP socket processing.                                            */  /*-------------------------------------------------------------------*/  else  {    /*-----------------------------------------------------------------*/    /* Verify destination IP address is an available address.          */    /*-----------------------------------------------------------------*/    if (route->flags & RT_BRDCST)      NetError(sock, EADDRNOTAVAIL);    /*-----------------------------------------------------------------*/    /* Else perform active TCP connection.                             */    /*-----------------------------------------------------------------*/    else      rc = tcp_conn(sock);  }conn_exit:  /*-------------------------------------------------------------------*/  /* Release exclusive API and internals access. Return status code.   */  /*-------------------------------------------------------------------*/  semPost(sock->api_access);  semPost(Net.IntSem);  return rc;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -