summaryrefslogtreecommitdiffstats
path: root/sock_stuff.c
diff options
context:
space:
mode:
Diffstat (limited to 'sock_stuff.c')
-rw-r--r--sock_stuff.c277
1 files changed, 277 insertions, 0 deletions
diff --git a/sock_stuff.c b/sock_stuff.c
new file mode 100644
index 0000000..1a23bc1
--- /dev/null
+++ b/sock_stuff.c
@@ -0,0 +1,277 @@
1#include <stdio.h>
2#include <stddef.h>
3#include <unistd.h>
4#include <errno.h>
5#include <sys/time.h>
6#include <sys/stat.h>
7#include <sys/socket.h>
8#include <sys/un.h>
9#include <netinet/in.h>
10#include <netdb.h>
11#include <arpa/inet.h>
12#include "sock_stuff.h"
13
14#define RECV_TIMEOUT 10000
15
16int create_unix_socket (const char *filename)
17{
18 struct sockaddr_un name;
19 int sock;
20 size_t size;
21
22 // remove if still present
23 unlink(filename);
24
25 /* Create the socket. */
26 sock = socket (PF_LOCAL, SOCK_STREAM, 0);
27 if (sock < 0) {
28 perror ("socket");
29 return -1;
30 }
31
32 /* Bind a name to the socket. */
33 name.sun_family = AF_LOCAL;
34 strncpy (name.sun_path, filename, sizeof (name.sun_path));
35 name.sun_path[sizeof (name.sun_path) - 1] = '\0';
36
37 /* The size of the address is
38 the offset of the start of the filename,
39 plus its length,
40 plus one for the terminating null byte.
41 Alternatively you can just do:
42 size = SUN_LEN (&name);
43 */
44 size = (offsetof (struct sockaddr_un, sun_path)
45 + strlen (name.sun_path) + 1);
46
47 if (bind (sock, (struct sockaddr *) &name, size) < 0) {
48 perror("bind");
49 close(sock);
50 return -1;
51 }
52
53 if (listen(sock, 10) < 0) {
54 perror("listen");
55 close(sock);
56 return -1;
57 }
58
59 return sock;
60}
61
62int connect_unix_socket(const char *filename)
63{
64 struct sockaddr_un name;
65 int sfd = -1;
66 size_t size;
67 struct stat fst;
68
69 // check if socket file exists...
70 if (stat(filename, &fst) != 0) {
71 fprintf(stderr, "%s: stat '%s': %s\n", __func__, filename, strerror(errno));
72 return -1;
73 }
74
75 // ... and if it is a unix domain socket
76 if (!S_ISSOCK(fst.st_mode)) {
77 fprintf(stderr, "%s: File '%s' is not a socket!\n", __func__, filename);
78 return -1;
79 }
80
81 // make a new socket
82 if ((sfd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) {
83 fprintf(stderr, "%s: socket: %s\n", __func__, strerror(errno));
84 return -1;
85 }
86
87 // and connect to 'filename'
88 name.sun_family = AF_LOCAL;
89 strncpy(name.sun_path, filename, sizeof(name.sun_path));
90 name.sun_path[sizeof(name.sun_path) - 1] = 0;
91
92 size = (offsetof (struct sockaddr_un, sun_path)
93 + strlen (name.sun_path) + 1);
94
95 if (connect(sfd, (struct sockaddr*)&name, size) < 0) {
96 close(sfd);
97 fprintf(stderr, "%s: connect: %s\n", __func__, strerror(errno));
98 return -1;
99 }
100
101 return sfd;
102}
103
104int create_socket(uint16_t port)
105{
106 int sfd = -1;
107 int yes = 1;
108 struct sockaddr_in saddr;
109
110 if ( 0 > ( sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) ) ) {
111 perror("socket()");
112 return -1;
113 }
114
115 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
116 perror("setsockopt()");
117 close(sfd);
118 return -1;
119 }
120
121 memset((void *)&saddr, 0, sizeof(saddr));
122 saddr.sin_family = AF_INET;
123 saddr.sin_addr.s_addr = htonl(INADDR_ANY);
124 saddr.sin_port = htons(port);
125
126 if(0 > bind(sfd, (struct sockaddr *)&saddr , sizeof(saddr))) {
127 perror("bind()");
128 close(sfd);
129 return -1;
130 }
131
132 if (listen(sfd, 1) == -1) {
133 perror("listen()");
134 close(sfd);
135 return -1;
136 }
137
138 return sfd;
139}
140
141int connect_socket(const char *addr, uint16_t port)
142{
143 int sfd = -1;
144 int yes = 1;
145 struct hostent *hp;
146 struct sockaddr_in saddr;
147
148 if (!addr) {
149 errno = EINVAL;
150 return -1;
151 }
152
153 if ((hp = gethostbyname(addr)) == NULL) {
154 fprintf(stderr, "%s: unknown host '%s'\n", __func__, addr);
155 return -1;
156 }
157
158 if (!hp->h_addr) {
159 fprintf(stderr, "%s: gethostbyname returned NULL address!\n", __func__);
160 return -1;
161 }
162
163 if ( 0 > ( sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) ) ) {
164 perror("socket()");
165 return -1;
166 }
167
168 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
169 perror("setsockopt()");
170 close(sfd);
171 return -1;
172 }
173
174 memset((void *)&saddr, 0, sizeof(saddr));
175 saddr.sin_family = AF_INET;
176 saddr.sin_addr.s_addr = (uint32_t)hp->h_addr;
177 saddr.sin_port = htons(port);
178
179 if (connect(sfd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0) {
180 perror("connect");
181 close(sfd);
182 return -2;
183 }
184
185 return sfd;
186}
187
188int check_fd(int fd, fd_mode fdm, unsigned int timeout)
189{
190 fd_set fds;
191 int sret;
192 int eagain;
193 struct timeval to;
194
195 if (fd <= 0) {
196 fprintf(stderr, "ERROR: invalid fd in check_fd %d\n", fd);
197 return -1;
198 }
199
200 FD_ZERO(&fds);
201 FD_SET(fd, &fds);
202
203 to.tv_sec = (time_t)(timeout/1000);
204 to.tv_usec = (time_t)((timeout-(to.tv_sec*1000))*1000);
205
206 sret = -1;
207
208 do {
209 eagain = 0;
210 switch(fdm) {
211 case fdread:
212 sret = select(fd+1,&fds,NULL,NULL,&to);
213 break;
214 case fdwrite:
215 sret = select(fd+1,NULL,&fds,NULL,&to);
216 break;
217 case fdexcept:
218 sret = select(fd+1,NULL,NULL,&fds,&to);
219 break;
220 }
221
222 if (sret < 0) {
223 switch(errno) {
224 case EINTR:
225 // interrupt signal in select
226 fprintf(stderr, "%s: EINTR\n", __func__);
227 eagain = 1;
228 break;
229 case EAGAIN:
230 fprintf(stderr, "%s: EAGAIN\n", __func__);
231 break;
232 default:
233 fprintf(stderr, "%s: select failed: %s\n", __func__, strerror(errno));
234 return -1;
235 }
236 }
237 } while (eagain);
238
239 return sret;
240}
241
242int recv_buf(int fd, void *data, size_t length)
243{
244 return recv_buf_timeout(fd, data, length, 0, RECV_TIMEOUT);
245}
246
247int peek_buf(int fd, void *data, size_t length)
248{
249 return recv_buf_timeout(fd, data, length, MSG_PEEK, RECV_TIMEOUT);
250}
251
252int recv_buf_timeout(int fd, void *data, size_t length, int flags, unsigned int timeout)
253{
254 int res;
255 int result;
256
257 // check if data is available
258 res = check_fd(fd, fdread, timeout);
259 if (res <= 0) {
260 return res;
261 }
262
263 // if we get here, there _is_ data available
264 result = recv(fd, data, length, flags);
265 if (res > 0 && result == 0) {
266 // but this is an error condition
267 fprintf(stderr, "%s: fd=%d\n", __func__, fd);
268 return -1;
269 }
270 return result;
271}
272
273int send_buf(int fd, void *data, size_t length)
274{
275 return send(fd, data, length, 0);
276}
277