Watt-32 tcp/ip  2.2 dev-rel.10
close.c
Go to the documentation of this file.
1 
5 /*
6  * BSD sockets functionality for Watt-32 TCP/IP
7  *
8  * Copyright (c) 1997-2002 Gisle Vanem <gvanem@yahoo.no>
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  * must display the following acknowledgement:
20  * This product includes software developed by Gisle Vanem
21  * Bergen, Norway.
22  *
23  * THIS SOFTWARE IS PROVIDED BY ME (Gisle Vanem) AND CONTRIBUTORS ``AS IS''
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL I OR CONTRIBUTORS BE LIABLE FOR ANY
27  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Version
35  *
36  * 0.5 : Dec 18, 1997 : G. Vanem - created
37  */
38 
39 #include "socket.h"
40 
41 #if defined(USE_BSD_API)
42 
43 static int close_dgram (Socket *socket);
44 static int close_stream (Socket *socket);
45 
46 int W32_CALL close_s (int s)
47 {
49 
50  SOCK_PROLOGUE (socket, "\nclose_s:%d", s);
51 
52  socket->so_error = 0;
53 
54  switch (socket->so_type)
55  {
56  case SOCK_PACKET:
57  case SOCK_RAW:
58  SOCK_DEL_FD (s);
59  return (0);
60 
61  case SOCK_DGRAM:
62  return close_dgram (socket);
63 
64  case SOCK_STREAM:
65  return close_stream (socket);
66  }
67  SOCK_ERRNO (EOPNOTSUPP);
68  return (-1);
69 }
70 
71 int W32_CALL closesocket (int s)
72 {
73  return close_s (s);
74 }
75 
76 /*
77  * Close a SOCK_DGRAM socket
78  */
79 static int close_dgram (Socket *socket)
80 {
81  sock_type *sk = (sock_type*)socket->udp_sock;
82 
83  sk->udp.rx_datalen = 0; /* flush Rx data */
84  sock_close (sk);
85  socket->so_state |= (SS_ISDISCONNECTING | SS_CANTSENDMORE);
86 
87  if (!socket->local_addr)
88  SOCK_DEL_FD (socket->fd);
89  return (0);
90 }
91 
92 /*
93  * Close a SOCK_STREAM socket
94  */
95 static int close_stream (Socket *socket)
96 {
97  sock_type *sk = (sock_type*)socket->tcp_sock;
98  BOOL abort_it = FALSE;
99  BOOL blocking_close = FALSE;
100  int i, s;
101 
102  if ((socket->so_state & SS_ISDISCONNECTING) && socket->close_time)
103  {
104  SOCK_DEBUGF ((", close already called"));
105  SOCK_ERRNO (EBADF);
106  return (-1);
107  }
108 
109  if (socket->so_options & SO_LINGER)
110  {
111  if (socket->linger_time == 0)
112  {
113  abort_it = TRUE;
114  sk = NULL;
115  SOCK_DEBUGF ((", zero-linger RST"));
116  }
117  else if (socket->linger_time > 0 && socket->linger_on)
118  {
119  blocking_close = TRUE;
120  SOCK_DEBUGF ((", blocking lingering close"));
121  }
122  }
123 
124  if (!socket->local_addr) /* Not bound or never received anything */
125  {
126  abort_it = TRUE;
127  sk = NULL;
128  }
129 
130  /* Save memory and abort listen() socket and queue now.
131  */
132  if (socket->so_options & SO_ACCEPTCONN)
133  {
134  SOCK_DEBUGF ((", listen abort, backlog %d", socket->backlog));
135  abort_it = TRUE;
136  sk = NULL;
137  for (i = 0; i < socket->backlog && i < SOMAXCONN; i++)
138  {
139  sock_type *tcb = (sock_type*) socket->listen_queue[i];
140 
141  if (!tcb)
142  continue;
143 
144  tcb->tcp.rx_datalen = 0; /* flush Rx data */
145  TCP_ABORT (&tcb->tcp);
146  free (tcb);
147  socket->listen_queue[i] = NULL;
148  }
149  }
150 
151  if (sk)
152  {
153  sk->tcp.rx_datalen = 0;
154  sock_flush (sk);
155  sock_close (sk);
156  }
157 
158  s = socket->fd;
159 
160  if (abort_it)
161  {
162  SOCK_DEBUGF ((", fast kill!"));
163  SOCK_DEL_FD (s); /* calls _tcp_abort() */
164  }
165  else
166  {
167  /* sock_daemon() will free socket from list and inuse array.
168  * Local port is marked for reuse after TCP_LINGERTIME (2min).
169  */
170  socket->so_state |= (SS_ISDISCONNECTING | SS_CANTSENDMORE);
171  socket->so_state |= SS_CANTRCVMORE; /* !! should we do this? */
172  socket->close_time = time (NULL);
173  }
174 
175  if (blocking_close)
176  {
177  while (_socklist_find(s)) /* while still alive */
178  {
179  tcp_tick (NULL); /* poll, sock_daemon() will delete it */
180  WATT_YIELD();
181  }
182  }
183  return (0);
184 }
185 #endif /* USE_BSD_API */
Definition: socket.h:137
int W32_CALL sock_close(sock_type *s)
Close a UDP/TCP socket.
Definition: pctcp.c:3139
void W32_CALL sock_flush(sock_type *s)
Send pending TCP data.
Definition: pctcp.c:3103
Definition: if.h:84
Socket * _socklist_find(int s)
Returns a pointer to the Socket structure associated with socket 's'.
Definition: socket.c:1534
WORD W32_CALL tcp_tick(sock_type *s)
Must be called periodically by user application (or BSD socket API).
Definition: pctcp.c:1389