📄 tcp_ip.c
字号:
/***********************************************************************/void SockRelease(SOCKET sock){ /*-------------------------------------------------------------------*/ /* Decrement socket reservation count and return if not zero. */ /*-------------------------------------------------------------------*/ TcpAssert(sock->reserve_cnt > 0); if (--sock->reserve_cnt) return; /*-------------------------------------------------------------------*/ /* Check if releasing a TCP socket. */ /*-------------------------------------------------------------------*/ if (sock->type == SOCK_STREAM) { /*-----------------------------------------------------------------*/ /* Ensure socket is stripped of TCP resources. */ /*-----------------------------------------------------------------*/ TcpStrip(sock, FREE_RBUF | FREE_SBUF); /*-----------------------------------------------------------------*/ /* Ensure all socket timers are stopped. */ /*-----------------------------------------------------------------*/ NetTimerStop(&sock->state_tmr); NetTimerStop(&sock->out_tmr); NetTimerStop(&sock->ack_tmr); } /*-------------------------------------------------------------------*/ /* Else free any datagrams queued on UDP socket. */ /*-------------------------------------------------------------------*/ else { while (sock->rq_head) { NetBuf *buf = sock->rq_head; sock->rq_head = buf->next; tcpRetBuf(&buf); } } /*-------------------------------------------------------------------*/ /* Remove from respective TCP or UDP socket list. */ /*-------------------------------------------------------------------*/ sock->link.next_bck->next_fwd = sock->link.next_fwd; sock->link.next_fwd->next_bck = sock->link.next_bck; /*-------------------------------------------------------------------*/ /* If not deleted, delete API access semaphore. */ /*-------------------------------------------------------------------*/ if (sock->api_access) { semDelete(sock->api_access); sock->api_access = NULL; } /*-------------------------------------------------------------------*/ /* Mark as "free" and place on end of free list. */ /*-------------------------------------------------------------------*/ sock->state = SS_FREE; sock->link.next_fwd = NetSockList.next_fwd; sock->link.next_bck = &NetSockList; NetSockList.next_fwd->next_bck = &sock->link; NetSockList.next_fwd = &sock->link; ++Net.SockCount;}/***********************************************************************//* SockAlloc: Allocate and initialize a new socket control block *//* *//* Input: type = SOCK_DGRAM or SOCK_STREAM *//* *//***********************************************************************/SOCKET SockAlloc(int type){ char name[9]; SOCKET sock = (SOCKET)NetSockList.next_bck; SEM api_access; /*-------------------------------------------------------------------*/ /* Return NULL if list of free sockets is empty. */ /*-------------------------------------------------------------------*/ if (NetSockList.next_bck == &NetSockList) return NULL; /*-------------------------------------------------------------------*/ /* Allocate API access semaphore. */ /*-------------------------------------------------------------------*/ sprintf(name, "sa%u", (sock - &Socks[0]) + 1); api_access = semCreate(name, 1, OS_FIFO); if (api_access == NULL) return NULL; /*-------------------------------------------------------------------*/ /* Remove socket from free list and track low water mark. */ /*-------------------------------------------------------------------*/ NetSockList.next_bck = NetSockList.next_bck->next_bck; NetSockList.next_bck->next_fwd = &NetSockList; if (--Net.SockCount < Net.SockMin) Net.SockMin = Net.SockCount; /*-------------------------------------------------------------------*/ /* Clear all uninitialized fields (required for UDP/TCPFreeSock()). */ /*-------------------------------------------------------------------*/ memset(sock, 0, sizeof(struct socket)); /*-------------------------------------------------------------------*/ /* Add socket to appropriate protocol socket list. */ /*-------------------------------------------------------------------*/ if (type == SOCK_DGRAM) { sock->link.next_fwd = UdpLruList.next_fwd; sock->link.next_bck = &UdpLruList; UdpLruList.next_fwd->next_bck = &sock->link; UdpLruList.next_fwd = &sock->link; } else { TcpAssert(type == SOCK_STREAM); sock->link.next_fwd = TcpLruList.next_fwd; sock->link.next_bck = &TcpLruList; TcpLruList.next_fwd->next_bck = &sock->link; TcpLruList.next_fwd = &sock->link; } /*-------------------------------------------------------------------*/ /* Initialize TCP/UDP common fields. */ /*-------------------------------------------------------------------*/ sock->api_access = api_access; sock->recv_timeo = sock->send_timeo = WAIT_FOREVER; sock->connect_timeo = 75 * TICKS_PER_SEC; sock->reserve_cnt = 1; sock->state = SS_CLOSED; sock->type = type; /*-------------------------------------------------------------------*/ /* Return pointer to socket. */ /*-------------------------------------------------------------------*/ return sock;}/***********************************************************************//* NetError: Process TCP/IP errors *//* *//* Inputs: sock = NULL or pointer to socket control block *//* err_code = API error code *//* *//***********************************************************************/void NetError(SOCKET sock, int err_code){ /*-------------------------------------------------------------------*/ /* Set errno and, if handle provided, socket error code. */ /*-------------------------------------------------------------------*/ errno = err_code; if (sock) sock->error = err_code;}/***********************************************************************//* NetPostEvent: Wake application task if waiting for posted event *//* *//* Inputs: sock = pointer to socket control block *//* events = bit mask for events being posted *//* *//***********************************************************************/void NetPostEvent(SOCKET sock, ui32 events){ /*-------------------------------------------------------------------*/ /* Wake application task waiting for events being posted. */ /*-------------------------------------------------------------------*/ if (sock->events & events) { sock->events = 0; taskWake(sock->taskid); } /*-------------------------------------------------------------------*/ /* Wake task blocked on select() if waiting for these events. */ /*-------------------------------------------------------------------*/ if (sock->sel_id && (sock->sel_evnts & events)) { sock->sel_evnts = 0; taskWake(sock->sel_id); } /*-------------------------------------------------------------------*/ /* If installed, use callback function to report socket event. */ /*-------------------------------------------------------------------*/ if (sock->report) sock->report(sock - &Socks[0] + 1, events);}/***********************************************************************//* NetPendEvent: Wait for specified event with optional timeout *//* *//* Inputs: sock = pointer to socket control block *//* events = bit mask for events caller is waiting for *//* timeout = maximum number of ticks to wait *//* *//***********************************************************************/void NetPendEvent(SOCKET sock, ui32 events, ui32 timeout){ /*-------------------------------------------------------------------*/ /* Clear socket's error values. */ /*-------------------------------------------------------------------*/ sock->soft_error = sock->error = 0; /*-------------------------------------------------------------------*/ /* Save our task id and set the event bits we are pending for. */ /*-------------------------------------------------------------------*/ sock->taskid = RunningTask; sock->events = events; /*-------------------------------------------------------------------*/ /* Prevent preemption between releasing internal access and sleeping.*/ /*-------------------------------------------------------------------*/ taskLock(); /*-------------------------------------------------------------------*/ /* Wait for event, releasing and re-acquiring internal access. */ /*-------------------------------------------------------------------*/ semPost(Net.IntSem); taskSleep(timeout); semPend(Net.IntSem, WAIT_FOREVER); /*-------------------------------------------------------------------*/ /* If events not received, we timed out. Set error value. */ /*-------------------------------------------------------------------*/ if ((sock->events & events) == events) sock->error = ETIMEDOUT; /*-------------------------------------------------------------------*/ /* Clear bits from event mask. */ /*-------------------------------------------------------------------*/ sock->events = 0; /*-------------------------------------------------------------------*/ /* Promote soft error if timeout or connection abort occurred. */ /*-------------------------------------------------------------------*/ if (sock->soft_error) { if (sock->error == ETIMEDOUT) { if (sock->type == SOCK_STREAM) TcpDrop(sock, sock->soft_error); else sock->error = sock->soft_error; } else if (sock->error == ECONNABORTED) sock->error = sock->soft_error; }}/***********************************************************************//* tcpDiag: Output TargetTCP diagnostics *//* *//* Input: type = type of diagnostic to report *//* *//***********************************************************************/void tcpDiag(int type){ /*-------------------------------------------------------------------*/ /* Verify protocol has been initialized. */ /*-------------------------------------------------------------------*/ if (!Net.Initialized) { NetError(NULL, ENETDOWN); return; } /*-------------------------------------------------------------------*/ /* Acquire exclusive access to protocol internals. */ /*-------------------------------------------------------------------*/ semPend(Net.IntSem, WAIT_FOREVER); /*-------------------------------------------------------------------*/ /* If requested, report on socket use. */ /*-------------------------------------------------------------------*/ if (type & TCP_DIAG_SOCK) { TcpQuerySock(); UdpQuerySock(); } /*-------------------------------------------------------------------*/ /* If requested, display ARP table. */ /*-------------------------------------------------------------------*/ if (type & TCP_DIAG_ARP) NetQueryArp(); /*-------------------------------------------------------------------*/ /* If requested, report on buffer use. */ /*-------------------------------------------------------------------*/ if (type & TCP_DIAG_BUFS) NetQueryBuf();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -