Imported Upstream version 3.2.0
[platform/upstream/libwebsockets.git] / lib / plat / unix / unix-fds.c
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010-2019 Andy Green <andy@warmcat.com>
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation:
9  *  version 2.1 of the License.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *  MA  02110-1301  USA
20  */
21
22 #define _GNU_SOURCE
23 #include "core/private.h"
24
25 struct lws *
26 wsi_from_fd(const struct lws_context *context, int fd)
27 {
28         struct lws **p, **done;
29
30         if (!context->max_fds_unrelated_to_ulimit)
31                 return context->lws_lookup[fd - lws_plat_socket_offset()];
32
33         /* slow fds handling */
34
35         p = context->lws_lookup;
36         done = &p[context->max_fds];
37
38         while (p != done) {
39                 if (*p && (*p)->desc.sockfd == fd)
40                         return *p;
41                 p++;
42         }
43
44         return NULL;
45 }
46
47 int
48 insert_wsi(const struct lws_context *context, struct lws *wsi)
49 {
50         struct lws **p, **done;
51
52         if (!context->max_fds_unrelated_to_ulimit) {
53                 assert(context->lws_lookup[wsi->desc.sockfd -
54                                            lws_plat_socket_offset()] == 0);
55
56                 context->lws_lookup[wsi->desc.sockfd - \
57                                   lws_plat_socket_offset()] = wsi;
58
59                 return 0;
60         }
61
62         /* slow fds handling */
63
64         p = context->lws_lookup;
65         done = &p[context->max_fds];
66
67 #if defined(_DEBUG)
68
69         /* confirm it doesn't already exist */
70
71         while (p != done && *p != wsi)
72                 p++;
73
74         assert(p == done);
75         p = context->lws_lookup;
76
77         /* confirm fd doesn't already exist */
78
79         while (p != done && (!*p || (*p && (*p)->desc.sockfd != wsi->desc.sockfd)))
80                 p++;
81
82         if (p != done) {
83                 lwsl_err("%s: wsi %p already says it has fd %d\n",
84                                 __func__, *p, wsi->desc.sockfd);
85                 assert(0);
86         }
87         p = context->lws_lookup;
88 #endif
89
90         /* find an empty slot */
91
92         while (p != done && *p)
93                 p++;
94
95         if (p == done) {
96                 lwsl_err("%s: reached max fds\n", __func__);
97                 return 1;
98         }
99
100         *p = wsi;
101
102         return 0;
103 }
104
105 void
106 delete_from_fd(const struct lws_context *context, int fd)
107 {
108
109         struct lws **p, **done;
110
111         if (!context->max_fds_unrelated_to_ulimit) {
112                 context->lws_lookup[fd - lws_plat_socket_offset()] = NULL;
113
114                 return;
115         }
116
117         /* slow fds handling */
118
119         p = context->lws_lookup;
120         done = &p[context->max_fds];
121
122         /* find the match */
123
124         while (p != done && (!*p || (*p && (*p)->desc.sockfd != fd)))
125                 p++;
126
127         if (p == done)
128                 lwsl_err("%s: fd %d not found\n", __func__, fd);
129         else
130                 *p = NULL;
131
132 #if defined(_DEBUG)
133         p = context->lws_lookup;
134         while (p != done && (!*p || (*p && (*p)->desc.sockfd != fd)))
135                 p++;
136
137         if (p != done) {
138                 lwsl_err("%s: fd %d in lws_lookup again at %d\n", __func__,
139                                 fd, (int)(p - context->lws_lookup));
140                 assert(0);
141         }
142 #endif
143 }
144
145 void
146 lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi)
147 {
148         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
149
150         if (context->event_loop_ops->io)
151                 context->event_loop_ops->io(wsi, LWS_EV_START | LWS_EV_READ);
152
153         pt->fds[pt->fds_count++].revents = 0;
154 }
155
156 void
157 lws_plat_delete_socket_from_fds(struct lws_context *context,
158                                                 struct lws *wsi, int m)
159 {
160         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
161
162         if (context->event_loop_ops->io)
163                 context->event_loop_ops->io(wsi,
164                                 LWS_EV_STOP | LWS_EV_READ | LWS_EV_WRITE);
165
166         pt->fds_count--;
167 }
168
169 int
170 lws_plat_change_pollfd(struct lws_context *context,
171                       struct lws *wsi, struct lws_pollfd *pfd)
172 {
173         return 0;
174 }