diff options
| author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-01-21 18:40:52 +0000 |
|---|---|---|
| committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-01-21 18:40:52 +0000 |
| commit | 195069cf5f929f445b0ce20e531cd482d2559083 (patch) | |
| tree | 6444d37c4ce32395428ba26ee0d16c0c372bd9da /src/usocket.c | |
| parent | e63f500d24ff0238425c9e13f220daf09a277ef5 (diff) | |
| download | luasocket-195069cf5f929f445b0ce20e531cd482d2559083.tar.gz luasocket-195069cf5f929f445b0ce20e531cd482d2559083.tar.bz2 luasocket-195069cf5f929f445b0ce20e531cd482d2559083.zip | |
Fixed functions that return messages in ?socket.c.
Moved complexity of connect and accept there.
Created a new options.c module to take care of options.
Auxiliar.c is now cleaner.
Diffstat (limited to 'src/usocket.c')
| -rw-r--r-- | src/usocket.c | 78 |
1 files changed, 45 insertions, 33 deletions
diff --git a/src/usocket.c b/src/usocket.c index f5939a9..54f203b 100644 --- a/src/usocket.c +++ b/src/usocket.c | |||
| @@ -20,6 +20,10 @@ | |||
| 20 | 20 | ||
| 21 | #include "socket.h" | 21 | #include "socket.h" |
| 22 | 22 | ||
| 23 | static const char *sock_createstrerror(void); | ||
| 24 | static const char *sock_bindstrerror(void); | ||
| 25 | static const char *sock_connectstrerror(void); | ||
| 26 | |||
| 23 | /*-------------------------------------------------------------------------*\ | 27 | /*-------------------------------------------------------------------------*\ |
| 24 | * Initializes module | 28 | * Initializes module |
| 25 | \*-------------------------------------------------------------------------*/ | 29 | \*-------------------------------------------------------------------------*/ |
| @@ -50,31 +54,37 @@ void sock_destroy(p_sock ps) | |||
| 50 | /*-------------------------------------------------------------------------*\ | 54 | /*-------------------------------------------------------------------------*\ |
| 51 | * Creates and sets up a socket | 55 | * Creates and sets up a socket |
| 52 | \*-------------------------------------------------------------------------*/ | 56 | \*-------------------------------------------------------------------------*/ |
| 53 | int sock_create(p_sock ps, int domain, int type, int protocol) | 57 | const char *sock_create(p_sock ps, int domain, int type, int protocol) |
| 54 | { | 58 | { |
| 55 | int val = 1; | 59 | int val = 1; |
| 56 | t_sock sock = socket(domain, type, protocol); | 60 | t_sock sock = socket(domain, type, protocol); |
| 57 | if (sock == SOCK_INVALID) return IO_ERROR; | 61 | if (sock == SOCK_INVALID) return sock_createstrerror(); |
| 58 | *ps = sock; | 62 | *ps = sock; |
| 59 | sock_setnonblocking(ps); | 63 | sock_setnonblocking(ps); |
| 60 | setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val)); | 64 | setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val)); |
| 61 | return IO_DONE; | 65 | return NULL; |
| 62 | } | 66 | } |
| 63 | 67 | ||
| 64 | /*-------------------------------------------------------------------------*\ | 68 | /*-------------------------------------------------------------------------*\ |
| 65 | * Connects or returns error message | 69 | * Connects or returns error message |
| 66 | \*-------------------------------------------------------------------------*/ | 70 | \*-------------------------------------------------------------------------*/ |
| 67 | int sock_connect(p_sock ps, SA *addr, socklen_t addr_len, int timeout) | 71 | const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm) |
| 68 | { | 72 | { |
| 69 | t_sock sock = *ps; | 73 | t_sock sock = *ps; |
| 70 | if (sock == SOCK_INVALID) return IO_CLOSED; | 74 | int err; |
| 71 | /* if connect fails, we have to find out why */ | 75 | /* don't call on closed socket */ |
| 72 | if (connect(sock, addr, addr_len) < 0) { | 76 | if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED); |
| 77 | /* ask system to connect */ | ||
| 78 | err = connect(sock, addr, addr_len); | ||
| 79 | /* if no error, we're done */ | ||
| 80 | if (err == 0) return NULL; | ||
| 81 | /* make sure the system is trying to connect */ | ||
| 82 | if (errno != EINPROGRESS) return io_strerror(IO_ERROR); | ||
| 83 | /* wait for a timeout or for the system's answer */ | ||
| 84 | for ( ;; ) { | ||
| 73 | struct timeval tv; | 85 | struct timeval tv; |
| 74 | fd_set rfds, efds, wfds; | 86 | fd_set rfds, wfds, efds; |
| 75 | int err; | 87 | int timeout = tm_getretry(tm); |
| 76 | /* make sure the system is trying to connect */ | ||
| 77 | if (errno != EINPROGRESS) return IO_ERROR; | ||
| 78 | tv.tv_sec = timeout / 1000; | 88 | tv.tv_sec = timeout / 1000; |
| 79 | tv.tv_usec = (timeout % 1000) * 1000; | 89 | tv.tv_usec = (timeout % 1000) * 1000; |
| 80 | FD_ZERO(&rfds); FD_SET(sock, &rfds); | 90 | FD_ZERO(&rfds); FD_SET(sock, &rfds); |
| @@ -82,28 +92,29 @@ int sock_connect(p_sock ps, SA *addr, socklen_t addr_len, int timeout) | |||
| 82 | FD_ZERO(&efds); FD_SET(sock, &efds); | 92 | FD_ZERO(&efds); FD_SET(sock, &efds); |
| 83 | /* we run select to avoid busy waiting */ | 93 | /* we run select to avoid busy waiting */ |
| 84 | err = select(sock+1, &rfds, &wfds, &efds, timeout >= 0? &tv: NULL); | 94 | err = select(sock+1, &rfds, &wfds, &efds, timeout >= 0? &tv: NULL); |
| 85 | /* if select was interrupted, ask the user to retry */ | 95 | /* if select was interrupted, try again */ |
| 86 | if (err < 0 && errno == EINTR) return IO_RETRY; | 96 | if (err < 0 && errno == EINTR) continue; |
| 87 | /* if selects readable, try reading */ | 97 | /* if selects readable, try reading */ |
| 88 | if (err > 0) { | 98 | if (err > 0) { |
| 89 | char dummy; | 99 | char dummy; |
| 90 | /* try reading so that errno is set */ | 100 | /* recv will set errno to the value a blocking connect would set */ |
| 91 | if (recv(sock, &dummy, 0, 0) < 0 && errno != EAGAIN) | 101 | if (recv(sock, &dummy, 0, 0) < 0 && errno != EAGAIN) |
| 92 | return IO_ERROR; | 102 | return sock_connectstrerror(); |
| 93 | else return IO_DONE; | 103 | else |
| 104 | return NULL; | ||
| 94 | /* if no event happened, there was a timeout */ | 105 | /* if no event happened, there was a timeout */ |
| 95 | } else return IO_TIMEOUT; | 106 | } else return io_strerror(IO_TIMEOUT); |
| 96 | /* otherwise connection succeeded */ | 107 | } |
| 97 | } else return IO_DONE; | 108 | return io_strerror(IO_TIMEOUT); /* can't get here */ |
| 98 | } | 109 | } |
| 99 | 110 | ||
| 100 | /*-------------------------------------------------------------------------*\ | 111 | /*-------------------------------------------------------------------------*\ |
| 101 | * Binds or returns error message | 112 | * Binds or returns error message |
| 102 | \*-------------------------------------------------------------------------*/ | 113 | \*-------------------------------------------------------------------------*/ |
| 103 | int sock_bind(p_sock ps, SA *addr, socklen_t addr_len) | 114 | const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) |
| 104 | { | 115 | { |
| 105 | if (bind(*ps, addr, addr_len) < 0) return IO_ERROR; | 116 | if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror(); |
| 106 | else return IO_DONE; | 117 | else return NULL; |
| 107 | } | 118 | } |
| 108 | 119 | ||
| 109 | /*-------------------------------------------------------------------------*\ | 120 | /*-------------------------------------------------------------------------*\ |
| @@ -125,8 +136,7 @@ void sock_shutdown(p_sock ps, int how) | |||
| 125 | /*-------------------------------------------------------------------------*\ | 136 | /*-------------------------------------------------------------------------*\ |
| 126 | * Accept with timeout | 137 | * Accept with timeout |
| 127 | \*-------------------------------------------------------------------------*/ | 138 | \*-------------------------------------------------------------------------*/ |
| 128 | int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, | 139 | int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, p_tm tm) |
| 129 | int timeout) | ||
| 130 | { | 140 | { |
| 131 | t_sock sock = *ps; | 141 | t_sock sock = *ps; |
| 132 | SA dummy_addr; | 142 | SA dummy_addr; |
| @@ -134,19 +144,21 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, | |||
| 134 | if (sock == SOCK_INVALID) return IO_CLOSED; | 144 | if (sock == SOCK_INVALID) return IO_CLOSED; |
| 135 | if (!addr) addr = &dummy_addr; | 145 | if (!addr) addr = &dummy_addr; |
| 136 | if (!addr_len) addr_len = &dummy_len; | 146 | if (!addr_len) addr_len = &dummy_len; |
| 137 | *pa = accept(sock, addr, addr_len); | 147 | for (;;) { |
| 138 | if (*pa == SOCK_INVALID) { | 148 | int timeout = tm_getretry(tm); |
| 139 | struct timeval tv; | 149 | struct timeval tv; |
| 140 | fd_set fds; | 150 | fd_set fds; |
| 151 | *pa = accept(sock, addr, addr_len); | ||
| 152 | if (*pa != SOCK_INVALID) return IO_DONE; | ||
| 153 | if (timeout == 0) return IO_TIMEOUT; | ||
| 141 | tv.tv_sec = timeout / 1000; | 154 | tv.tv_sec = timeout / 1000; |
| 142 | tv.tv_usec = (timeout % 1000) * 1000; | 155 | tv.tv_usec = (timeout % 1000) * 1000; |
| 143 | FD_ZERO(&fds); | 156 | FD_ZERO(&fds); |
| 144 | FD_SET(sock, &fds); | 157 | FD_SET(sock, &fds); |
| 145 | /* just call select to avoid busy-wait. doesn't really matter | 158 | /* call select just to avoid busy-wait. */ |
| 146 | * what happens. the caller will choose to retry or not */ | ||
| 147 | select(sock+1, &fds, NULL, NULL, timeout >= 0? &tv: NULL); | 159 | select(sock+1, &fds, NULL, NULL, timeout >= 0? &tv: NULL); |
| 148 | return IO_RETRY; | 160 | } |
| 149 | } else return IO_DONE; | 161 | return IO_TIMEOUT; /* can't get here */ |
| 150 | } | 162 | } |
| 151 | 163 | ||
| 152 | /*-------------------------------------------------------------------------*\ | 164 | /*-------------------------------------------------------------------------*\ |
| @@ -314,7 +326,7 @@ const char *sock_hoststrerror(void) | |||
| 314 | } | 326 | } |
| 315 | } | 327 | } |
| 316 | 328 | ||
| 317 | const char *sock_createstrerror(void) | 329 | static const char *sock_createstrerror(void) |
| 318 | { | 330 | { |
| 319 | switch (errno) { | 331 | switch (errno) { |
| 320 | case EACCES: return "access denied"; | 332 | case EACCES: return "access denied"; |
| @@ -325,7 +337,7 @@ const char *sock_createstrerror(void) | |||
| 325 | } | 337 | } |
| 326 | } | 338 | } |
| 327 | 339 | ||
| 328 | const char *sock_bindstrerror(void) | 340 | static const char *sock_bindstrerror(void) |
| 329 | { | 341 | { |
| 330 | switch (errno) { | 342 | switch (errno) { |
| 331 | case EBADF: return "invalid descriptor"; | 343 | case EBADF: return "invalid descriptor"; |
| @@ -339,7 +351,7 @@ const char *sock_bindstrerror(void) | |||
| 339 | } | 351 | } |
| 340 | } | 352 | } |
| 341 | 353 | ||
| 342 | const char *sock_connectstrerror(void) | 354 | static const char *sock_connectstrerror(void) |
| 343 | { | 355 | { |
| 344 | switch (errno) { | 356 | switch (errno) { |
| 345 | case EBADF: return "invalid descriptor"; | 357 | case EBADF: return "invalid descriptor"; |
