📄 connect.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 + -