root/luci/trunk/libs/nixio/src/io.c @ 5414

Revision 5414, 3.9 KB (checked in by nbd, 4 years ago)

nixio: store stats and other number information as integer, which works better when lua number support is downgraded from double to float

Line 
1/*
2 * nixio - Linux I/O library for lua
3 *
4 *   Copyright (C) 2009 Steven Barth <steven@midlink.org>
5 *
6 *  Licensed under the Apache License, Version 2.0 (the "License");
7 *  you may not use this file except in compliance with the License.
8 *  You may obtain a copy of the License at
9 *
10 *      http://www.apache.org/licenses/LICENSE-2.0
11 *
12 *  Unless required by applicable law or agreed to in writing, software
13 *  distributed under the License is distributed on an "AS IS" BASIS,
14 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 *  See the License for the specific language governing permissions and
16 *  limitations under the License.
17 */
18
19#include "nixio.h"
20#include <errno.h>
21#include <string.h>
22#include <stdlib.h>
23#include <stdio.h>
24#include <sys/types.h>
25
26
27/**
28 * send() / sendto() helper
29 */
30static int nixio_sock__sendto(lua_State *L, int to) {
31    nixio_sock *sock = nixio__checksock(L);
32    struct sockaddr *addr = NULL;
33    socklen_t alen = 0;
34    int argoff = 2;
35
36    if (to) {
37        argoff += 2;
38        const char *address = luaL_checkstring(L, 3);
39        struct sockaddr_storage addrstor;
40        addr = (struct sockaddr*)&addrstor;
41
42        nixio_addr naddr;
43        memset(&naddr, 0, sizeof(naddr));
44        strncpy(naddr.host, address, sizeof(naddr.host) - 1);
45        naddr.port = (uint16_t)luaL_checkinteger(L, 4);
46        naddr.family = sock->domain;
47
48        if (nixio__addr_write(&naddr, addr)) {
49            return nixio__perror_s(L);
50        }
51    }
52
53    size_t len;
54    ssize_t sent;
55    const char *data = luaL_checklstring(L, 2, &len);
56
57    if (lua_gettop(L) > argoff) {
58        int offset = luaL_optint(L, argoff + 1, 0);
59        if (offset) {
60            if (offset < len) {
61                data += offset;
62                len -= offset;
63            } else {
64                len = 0;
65            }
66        }
67
68        unsigned int wlen = luaL_optint(L, argoff + 2, len);
69        if (wlen < len) {
70            len = wlen;
71        }
72    }
73
74    do {
75        sent = sendto(sock->fd, data, len, 0, addr, alen);
76    } while(sent == -1 && errno == EINTR);
77    if (sent >= 0) {
78        lua_pushinteger(L, sent);
79        return 1;
80    } else {
81        return nixio__perror_s(L);
82    }
83}
84
85/**
86 * send(data)
87 */
88static int nixio_sock_send(lua_State *L) {
89    return nixio_sock__sendto(L, 0);
90}
91
92/**
93 * sendto(data, address, port)
94 */
95static int nixio_sock_sendto(lua_State *L) {
96    return nixio_sock__sendto(L, 1);
97}
98
99
100/**
101 * recv() / recvfrom() helper
102 */
103static int nixio_sock__recvfrom(lua_State *L, int from) {
104    nixio_sock *sock = nixio__checksock(L);
105    char buffer[NIXIO_BUFFERSIZE];
106    struct sockaddr_storage addrobj;
107    uint req = luaL_checkinteger(L, 2);
108    int readc;
109
110    if (from && sock->domain != AF_INET && sock->domain != AF_INET6) {
111        return luaL_argerror(L, 1, "supported families: inet, inet6");
112    }
113
114    struct sockaddr *addr = (from) ? (struct sockaddr*)&addrobj : NULL;
115    socklen_t alen = (from) ? sizeof(addrobj) : 0;
116
117    /* We limit the readsize to NIXIO_BUFFERSIZE */
118    req = (req > NIXIO_BUFFERSIZE) ? NIXIO_BUFFERSIZE : req;
119
120    do {
121        readc = recvfrom(sock->fd, buffer, req, 0, addr, &alen);
122    } while (readc == -1 && errno == EINTR);
123
124#ifdef __WINNT__
125    if (readc < 0) {
126        int e = WSAGetLastError();
127        if (e == WSAECONNRESET || e == WSAECONNABORTED || e == WSAESHUTDOWN) {
128            readc = 0;
129        }
130    }
131#endif
132
133    if (readc < 0) {
134        return nixio__perror_s(L);
135    } else {
136        lua_pushlstring(L, buffer, readc);
137
138        if (!from) {
139            return 1;
140        } else {
141            nixio_addr naddr;
142            if (!nixio__addr_parse(&naddr, (struct sockaddr *)&addrobj)) {
143                lua_pushstring(L, naddr.host);
144                lua_pushinteger(L, naddr.port);
145                return 3;
146            } else {
147                return 1;
148            }
149        }
150    }
151}
152
153/**
154 * recv(count)
155 */
156static int nixio_sock_recv(lua_State *L) {
157    return nixio_sock__recvfrom(L, 0);
158}
159
160/**
161 * recvfrom(count)
162 */
163static int nixio_sock_recvfrom(lua_State *L) {
164    return nixio_sock__recvfrom(L, 1);
165}
166
167
168/* module table */
169static const luaL_reg M[] = {
170    {"send",    nixio_sock_send},
171    {"sendto",  nixio_sock_sendto},
172    {"recv",    nixio_sock_recv},
173    {"recvfrom",nixio_sock_recvfrom},
174    {"write",   nixio_sock_send},
175    {"read",    nixio_sock_recv},
176    {NULL,          NULL}
177};
178
179void nixio_open_io(lua_State *L) {
180    lua_pushvalue(L, -2);
181    luaL_register(L, NULL, M);
182    lua_pop(L, 1);
183}
Note: See TracBrowser for help on using the browser.