📄 shutdown.c
字号:
/***********************************************************************//* *//* Module: shutdown.c *//* Release: 2001.3 *//* Version: 99.0 *//* Purpose: shutdown() 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"/***********************************************************************//* Global Function Definitions *//***********************************************************************//***********************************************************************//* shutdown: Shutdown a socket connection *//* *//* Inputs: s = socket identifier *//* how = how connection is shutdown: SHUT_RD, SHUT_WR, or *//* SHUT_RDWR (0, 1, or 2) *//* *//***********************************************************************/int shutdown(int s, int how){ int rc = 0; SOCKET sock = &Socks[s - 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; } /*-------------------------------------------------------------------*/ /* Check that the value of how is valid. */ /*-------------------------------------------------------------------*/ if ((how < SHUT_RD) || (how > SHUT_RDWR)) { NetError(sock, EINVAL); 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); /*-------------------------------------------------------------------*/ /* If TCP socket, verify that it is connected. */ /*-------------------------------------------------------------------*/ if ((sock->type == SOCK_STREAM) && !(sock->flags & SF_CONNECTED)) { rc = -1; NetError(sock, ENOTCONN); goto shtdn_exit; } /*-------------------------------------------------------------------*/ /* Set shutdown flags and post shutdown event to socket. */ /*-------------------------------------------------------------------*/ if (how == SHUT_RD) { sock->flags |= SF_RCV_SHUT; NetPostEvent(sock, SE_RCV_SHUT); } else if (how == SHUT_WR) { sock->flags |= SF_SND_SHUT; NetPostEvent(sock, SE_SND_SHUT); } else { sock->flags |= SF_RCV_SHUT | SF_SND_SHUT; NetPostEvent(sock, SE_RCV_SHUT | SE_SND_SHUT); } /*-------------------------------------------------------------------*/ /* Check if shutting down further sends on connected TCP socket. */ /*-------------------------------------------------------------------*/ if (how && (sock->type == SOCK_STREAM)) { /*-----------------------------------------------------------------*/ /* Send FIN if it hasn't alread been sent. */ /*-----------------------------------------------------------------*/ if ((sock->state == SS_CLOSEWAIT) || (sock->state == SS_ESTABLISHED)) { /*---------------------------------------------------------------*/ /* Mark that FIN is needed and record its sequence number. */ /*---------------------------------------------------------------*/ sock->flags |= SF_SNDFIN; sock->fin_seq = sock->snt_una + sock->sb_count; /*---------------------------------------------------------------*/ /* Update state to either FIN_WAIT_1 or LAST_ACK. */ /*---------------------------------------------------------------*/ if (sock->state == SS_CLOSEWAIT) sock->state = SS_LASTACK; else /* state == ESTABLISHED */ sock->state = SS_FINWAIT1; /*---------------------------------------------------------------*/ /* Start output state machine. */ /*---------------------------------------------------------------*/ TcpTryOut(sock); } } /*-------------------------------------------------------------------*/ /* Check if shutting down further receives. */ /*-------------------------------------------------------------------*/ if (sock->flags & SF_RCV_SHUT) { /*-----------------------------------------------------------------*/ /* If TCP socket, free receive buffers and OOS queue. */ /*-----------------------------------------------------------------*/ if (sock->type == SOCK_STREAM) TcpStrip(sock, FREE_RBUF); /*-----------------------------------------------------------------*/ /* Else free UDP socket's datagram queue. */ /*-----------------------------------------------------------------*/ else { while (sock->rq_head) { NetBuf *buf = sock->rq_head; sock->rq_head = buf->next; tcpRetBuf(&buf); } } } /*-------------------------------------------------------------------*/ /* Release exclusive API and internals access. Return status code. */ /*-------------------------------------------------------------------*/shtdn_exit: semPost(sock->api_access); semPost(Net.IntSem); return rc;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -