net_sockets.c 7.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 * File      : lwip_sockets.c
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2015, RT-Thread Development Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Change Logs:
 * Date           Author       Notes
 * 2015-02-17     Bernard      First version
 */

#include <dfs.h>
26
#include <dfs_posix.h>
B
bernard 已提交
27
#include <dfs_poll.h>
28 29
#include <sys/socket.h>

30
#include "dfs_net.h"
31

B
bernard 已提交
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
{
    int s;
    struct lwip_sock *sock;
    uint32_t event = 0;
    SYS_ARCH_DECL_PROTECT(lev);

    LWIP_UNUSED_ARG(len);

    /* Get socket */
    if (conn)
    {
        s = conn->socket;
        if (s < 0)
        {
            /* Data comes in right away after an accept, even though
             * the server task might not have created a new socket yet.
             * Just count down (or up) if that's the case and we
             * will use the data later. Note that only receive events
             * can happen before the new socket is set up. */
            SYS_ARCH_PROTECT(lev);
            if (conn->socket < 0)
            {
                if (evt == NETCONN_EVT_RCVPLUS)
                {
                    conn->socket--;
                }
                SYS_ARCH_UNPROTECT(lev);
                return;
            }
            s = conn->socket;
            SYS_ARCH_UNPROTECT(lev);
        }

        sock = lwip_tryget_socket(s);
        if (!sock)
        {
            return;
        }
    }
    else
    {
        return;
    }

    SYS_ARCH_PROTECT(lev);
    /* Set event as required */
    switch (evt)
    {
    case NETCONN_EVT_RCVPLUS:
        sock->rcvevent++;
        break;
    case NETCONN_EVT_RCVMINUS:
        sock->rcvevent--;
        break;
    case NETCONN_EVT_SENDPLUS:
        sock->sendevent = 1;
        break;
    case NETCONN_EVT_SENDMINUS:
        sock->sendevent = 0;
        break;
    case NETCONN_EVT_ERROR:
        sock->errevent = 1;
        break;
    default:
        LWIP_ASSERT("unknown event", 0);
        break;
    }

    if (sock->lastdata || sock->rcvevent > 0) event |= POLLIN;
    if (sock->sendevent) event |= POLLOUT;
    if (sock->errevent)  event |= POLLERR;

    SYS_ARCH_UNPROTECT(lev);

    if (event)
    {
        rt_wqueue_wakeup(&sock->wait_head, (void*)event);
    }
}

113 114
int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
{
115
    int new_client = -1;
116
    int sock = dfs_net_getsocket(s);
117

118
    new_client = lwip_accept(sock, addr, addrlen);
119 120 121 122 123
    if (new_client != -1)
    {
        /* this is a new socket, create it in file system fd */
        int fd;
        struct dfs_fd *d;
B
bernard 已提交
124 125
        struct lwip_sock *lwsock;
        
126 127 128 129
        /* allocate a fd */
        fd = fd_new();
        if (fd < 0)
        {
B
bernard 已提交
130
            rt_set_errno(-ENOMEM);
131 132 133 134 135 136 137 138 139 140
            lwip_close(sock);

            return -1;
        }
        d = fd_get(fd);

        /* this is a socket fd */
        d->type = FT_SOCKET;
        d->path = RT_NULL;

B
bernard 已提交
141 142 143 144
        d->fops = dfs_net_get_fops();
        /* initialize wait head */
        lwsock = lwip_tryget_socket(new_client);
        rt_list_init(&(lwsock->wait_head));
145

B
bernard 已提交
146
        d->flags = O_RDWR; /* set flags as read and write */
147 148 149 150 151 152 153 154 155
        d->size = 0;
        d->pos  = 0;

        /* set socket to the data of dfs_fd */
        d->data = (void *) new_client;

        /* release the ref-count of fd */
        fd_put(d);

156
        return fd;
157
    }
158

159
    return new_client;
160
}
161
RTM_EXPORT(accept);
162 163 164

int bind(int s, const struct sockaddr *name, socklen_t namelen)
{
165
    int sock = dfs_net_getsocket(s);
166

167 168
    return lwip_bind(sock, name, namelen);
}
169
RTM_EXPORT(bind);
170 171 172

int shutdown(int s, int how)
{
173
    int sock;
174
    struct dfs_fd *d;
175

176 177 178
    d = fd_get(s);
    if (d == RT_NULL)
    {
B
bernard 已提交
179
        rt_set_errno(-EBADF);
180

181 182 183
        return -1;
    }

184
    sock = dfs_net_getsocket(s);
185 186
    if (lwip_shutdown(sock, how) == 0)
    {
187 188 189 190 191
        /* socket has been closed, delete it from file system fd */
        fd_put(d);
        fd_put(d);

        return 0;
192
    }
193

194
    return -1;
195
}
196
RTM_EXPORT(shutdown);
197

198
int getpeername(int s, struct sockaddr *name, socklen_t *namelen)
199
{
200
    int sock = dfs_net_getsocket(s);
201 202 203

    return lwip_getpeername(sock, name, namelen);
}
204
RTM_EXPORT(getpeername);
205

206
int getsockname(int s, struct sockaddr *name, socklen_t *namelen)
207
{
208
    int sock = dfs_net_getsocket(s);
209

210 211
    return lwip_getsockname(sock, name, namelen);
}
212
RTM_EXPORT(getsockname);
213

214
int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
215
{
216
    int sock = dfs_net_getsocket(s);
217

218 219
    return lwip_getsockopt(sock, level, optname, optval, optlen);
}
220
RTM_EXPORT(getsockopt);
221

222
int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
223
{
224
    int sock = dfs_net_getsocket(s);
225

226 227
    return lwip_setsockopt(sock, level, optname, optval, optlen);
}
228
RTM_EXPORT(setsockopt);
229 230 231

int connect(int s, const struct sockaddr *name, socklen_t namelen)
{
232
    int sock = dfs_net_getsocket(s);
233

234 235
    return lwip_connect(sock, name, namelen);
}
236
RTM_EXPORT(connect);
237 238 239

int listen(int s, int backlog)
{
240
    int sock = dfs_net_getsocket(s);
241

242 243
    return lwip_listen(sock, backlog);
}
244
RTM_EXPORT(listen);
245 246 247

int recv(int s, void *mem, size_t len, int flags)
{
248
    int sock = dfs_net_getsocket(s);
249

250 251
    return lwip_recv(sock, mem, len, flags);
}
252
RTM_EXPORT(recv);
253 254

int recvfrom(int s, void *mem, size_t len, int flags,
255
             struct sockaddr *from, socklen_t *fromlen)
256
{
257
    int sock = dfs_net_getsocket(s);
258

259 260
    return lwip_recvfrom(sock, mem, len, flags, from, fromlen);
}
261
RTM_EXPORT(recvfrom);
262 263 264

int send(int s, const void *dataptr, size_t size, int flags)
{
265
    int sock = dfs_net_getsocket(s);
266

267 268
    return lwip_send(sock, dataptr, size, flags);
}
269
RTM_EXPORT(send);
270 271

int sendto(int s, const void *dataptr, size_t size, int flags,
272
           const struct sockaddr *to, socklen_t tolen)
273
{
274
    int sock = dfs_net_getsocket(s);
275

276 277
    return lwip_sendto(sock, dataptr, size, flags, to, tolen);
}
278
RTM_EXPORT(sendto);
279 280 281 282 283 284 285

int socket(int domain, int type, int protocol)
{
    /* create a BSD socket */
    int fd;
    int sock;
    struct dfs_fd *d;
B
bernard 已提交
286
    struct lwip_sock *lwsock;
287 288 289 290 291

    /* allocate a fd */
    fd = fd_new();
    if (fd < 0)
    {
B
bernard 已提交
292
        rt_set_errno(-ENOMEM);
293 294 295 296 297 298 299

        return -1;
    }
    d = fd_get(fd);

    /* create socket in lwip and then put it to the dfs_fd */
    sock = lwip_socket(domain, type, protocol);
B
bernard 已提交
300
    if (sock >= 0)
301 302
    {
        /* this is a socket fd */
B
bernard 已提交
303 304
        d->type  = FT_SOCKET;
        d->path  = NULL;
305

B
bernard 已提交
306
        d->fops  = dfs_net_get_fops();
307

B
bernard 已提交
308 309 310
        d->flags = O_RDWR; /* set flags as read and write */
        d->size  = 0;
        d->pos   = 0;
311

312
        /* set socket to the data of dfs_fd */
313
        d->data = (void *) sock;
B
bernard 已提交
314 315 316 317

        lwsock = lwip_tryget_socket(sock);
        rt_list_init(&(lwsock->wait_head));
        lwsock->conn->callback = event_callback;
318 319 320 321 322 323 324
    }

    /* release the ref-count of fd */
    fd_put(d);

    return fd;
}
325
RTM_EXPORT(socket);
B
bernard 已提交
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342

int closesocket(int s)
{
    int sock = dfs_net_getsocket(s);

    return lwip_close(sock);
}
RTM_EXPORT(closesocket);

int ioctlsocket(int s, long cmd, void *arg)
{
    int sock = dfs_net_getsocket(s);

    return lwip_ioctl(sock, cmd, arg);
}
RTM_EXPORT(ioctlsocket);