src/usocket.c

1
/*=========================================================================*\
2
* LuaSocket 2.0.2
3
* Copyright (C) 2004-2007 Diego Nehab
4
*
5
* Socket compatibilization module for Unix
6
*
7
* The code is now interrupt-safe.
8
* The penalty of calling select to avoid busy-wait is only paid when
9
* the I/O call fail in the first place. 
10
*
11
* RCS ID: $Id: usocket.c,v 1.38 2007/10/13 23:55:20 diego Exp $
12
\*=========================================================================*/
13
#include <errno.h>
14
#include <sys/types.h>
15
#include <sys/time.h>
16
#include <sys/socket.h>
17
#include <string.h> 
18
#include <signal.h>
19
#include <unistd.h>
20
#include <fcntl.h>
21
 
22
#include "socket.h"
23
#include "usocket.h"
24
 
25
/*-------------------------------------------------------------------------*\
26
* Wait for readable/writable/connected socket with timeout
27
\*-------------------------------------------------------------------------*/
28
#ifdef SOCKET_POLL
29
int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
30
    int ret;
31
    struct pollfd pfd;
32
    pfd.fd = *ps;
33
    pfd.events = sw;
34
    pfd.revents = 0;
35
    if (timeout_iszero(tm)) return IO_TIMEOUT;  /* optimize timeout == 0 case */
36
    do {
37
        int t = (int)(timeout_getretry(tm)*1e3);
38
        ret = poll(&pfd, 1, t >= 0? t: -1);
39
    } while (ret == -1 && errno == EINTR);
40
    if (ret == -1) return errno;
41
    if (ret == 0) return IO_TIMEOUT;
42
    if (sw == WAITFD_C && (pfd.revents & (POLLIN|POLLERR))) return IO_CLOSED;
43
    return IO_DONE;
44
}
45
#else
46
int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
47
    int ret;
48
    fd_set rfds, wfds, *rp, *wp;
49
    struct timeval tv, *tp;
50
    double t;
51
    if (timeout_iszero(tm)) return IO_TIMEOUT;  /* optimize timeout == 0 case */
52
    do {
53
        /* must set bits within loop, because select may have modifed them */
54
        rp = wp = NULL;
55
        if (sw & WAITFD_R) { FD_ZERO(&rfds); FD_SET(*ps, &rfds); rp = &rfds; }
56
        if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; }
57
        t = timeout_getretry(tm);
58
        tp = NULL;
59
        if (t >= 0.0) {
60
            tv.tv_sec = (int)t;
61
            tv.tv_usec = (int)((t-tv.tv_sec)*1.0e6);
62
            tp = &tv;
63
        }
64
        ret = select(*ps+1, rp, wp, NULL, tp);
65
    } while (ret == -1 && errno == EINTR);
66
    if (ret == -1) return errno;
67
    if (ret == 0) return IO_TIMEOUT;
68
    if (sw == WAITFD_C && FD_ISSET(*ps, &rfds)) return IO_CLOSED;
69
    return IO_DONE;
70
}
71
#endif
72
 
73
 
74
/*-------------------------------------------------------------------------*\
75
* Initializes module 
76
\*-------------------------------------------------------------------------*/
77
int socket_open(void) {
78
    /* instals a handler to ignore sigpipe or it will crash us */
79
    signal(SIGPIPE, SIG_IGN);
80
    return 1;
81
}
82
 
83
/*-------------------------------------------------------------------------*\
84
* Close module 
85
\*-------------------------------------------------------------------------*/
86
int socket_close(void) {
87
    return 1;
88
}
89
 
90
/*-------------------------------------------------------------------------*\
91
* Close and inutilize socket
92
\*-------------------------------------------------------------------------*/
93
void socket_destroy(p_socket ps) {
94
    if (*ps != SOCKET_INVALID) {
95
        socket_setblocking(ps);
96
        close(*ps);
97
        *ps = SOCKET_INVALID;
98
    }
99
}
100
 
101
/*-------------------------------------------------------------------------*\
102
* Put socket into blocking mode
103
\*-------------------------------------------------------------------------*/
104
void socket_setblocking(p_socket ps) {
105
    int flags = fcntl(*ps, F_GETFL, 0);
106
    flags &= (~(O_NONBLOCK));
107
    fcntl(*ps, F_SETFL, flags);
108
}
109
 
110
/*-------------------------------------------------------------------------*\
111
* Put socket into non-blocking mode
112
\*-------------------------------------------------------------------------*/
113
void socket_setnonblocking(p_socket ps) {
114
    int flags = fcntl(*ps, F_GETFL, 0);
115
    flags |= O_NONBLOCK;
116
    fcntl(*ps, F_SETFL, flags);
117
}
118
 
119
/*-------------------------------------------------------------------------*\
120
* Error translation functions
121
* Make sure important error messages are standard
122
\*-------------------------------------------------------------------------*/
123
const char *socket_strerror(int err) {
124
    if (err <= 0) return io_strerror(err);
125
    switch (err) {
126
        case EADDRINUSE: return "address already in use";
127
        case EISCONN: return "already connected";
128
        case EACCES: return "permission denied";
129
        case ECONNREFUSED: return "connection refused";
130
        case ECONNABORTED: return "closed";
131
        case ECONNRESET: return "closed";
132
	case EPIPE: return "closed";
133
        case ETIMEDOUT: return "timeout";
134
        default: return strerror(errno);
135
    }
136
}
137
 
138
/*-------------------------------------------------------------------------*\
139
* Underline error code.
140
\*-------------------------------------------------------------------------*/
141
int socket_error()
142
{
143
  return errno;
144
}