-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsocket.c
160 lines (132 loc) · 2.46 KB
/
socket.c
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
26
27
28
29
30
31
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include "socket.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <poll.h>
#include <arpa/inet.h>
#include "log.h"
int
plxr_socket_listen(struct sockaddr_in *addr, int port)
{
int sockfd;
static int YES = 1;
bzero(addr, sizeof(struct sockaddr_in));
addr->sin_addr.s_addr = INADDR_ANY;
addr->sin_family = AF_INET;
addr->sin_port = htons(port);
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0))
== -1 )
{
ERROR("socket");
goto error;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &YES, sizeof(YES))
== -1 )
{
ERROR("setsockopt");
goto error;
}
if (bind(sockfd, (struct sockaddr *) addr, sizeof(*addr))
== -1 )
{
ERROR("bind");
goto error;
}
if (listen(sockfd, SOCK_STREAM)
== -1 )
{
ERROR("listen");
goto error;
}
return sockfd;
error:
close(sockfd); /* avoid leaking descriptors */
return -1;
}
/* TODO: handle EAGAIN, EWOULDBLOCK. see write(2) */
int
plxr_socket_write_timeout(
int fd,
const char *data,
size_t data_len,
int timeout_milliseconds
){
int ret;
struct pollfd pfd = {
.fd = fd,
.events = POLLOUT,
.revents = 0
};
switch (poll(&pfd, 1, timeout_milliseconds)) {
case -1:
ERROR("poll");
return -1;
case 0:
WARN("poll timeout");
return -1;
case 1:
if ((ret = write(fd, data, data_len)) == -1)
{
ERROR("write");
return -1;
}
if (ret != data_len)
{
WARN("wrote less than the desired nbytes");
return -1;
}
return ret; /* success! */
}
WARN("shouldn't get here");
return -1;
}
int
plxr_socket_read_timeout(
int fd,
char *data,
size_t data_max,
int timeout_milliseconds
){
int ret;
struct pollfd pfd = {
.fd = fd,
.events = POLLIN,
.revents = 0
};
switch (poll(&pfd, 1, timeout_milliseconds)) {
case -1:
ERROR("poll");
return -1;
case 0:
WARN("poll timeout");
return -1;
case 1: /* successful poll(2) */
ret = read(fd, (void *)data, data_max);
if (ret == -1)
{
ERROR("read");
return -1;
}
return ret;
default:
break;
}
WARN("shouldn't get here");
return -1;
}
static char ntop_buffer[INET_ADDRSTRLEN];
const char *
plxr_socket_ntop(struct sockaddr *addr)
{
struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
bzero(ntop_buffer, sizeof(ntop_buffer));
inet_ntop(AF_INET, &addr_in->sin_addr, ntop_buffer, INET_ADDRSTRLEN);
return (const char *) ntop_buffer;
}