1 | #include "rtserver.h" |
---|
2 | #include <stdio.h> |
---|
3 | #include <stdlib.h> |
---|
4 | #include <sys/types.h> |
---|
5 | #include <sys/socket.h> |
---|
6 | #include <sys/select.h> |
---|
7 | #include <time.h> |
---|
8 | #include <netdb.h> |
---|
9 | #include <netinet/in.h> |
---|
10 | #include <errno.h> |
---|
11 | |
---|
12 | |
---|
13 | /** Structure containing all the information necessary to run an rtserver */ |
---|
14 | struct rtserver_t { |
---|
15 | /** fd describing the listening socket */ |
---|
16 | int connect_fd; |
---|
17 | /** set of client fds */ |
---|
18 | fd_set rt_fds; |
---|
19 | /** the highest numbered fd */ |
---|
20 | int max_rtfds; |
---|
21 | /** sockaddr used to accept incoming connections */ |
---|
22 | struct sockaddr_in * remote; |
---|
23 | }; |
---|
24 | |
---|
25 | struct rtserver_t * rtserver_create (char * hostname, short port) { |
---|
26 | struct rtserver_t * rtserver = malloc(sizeof(struct rtserver_t)); |
---|
27 | struct hostent *he; |
---|
28 | int yes = 1; |
---|
29 | |
---|
30 | FD_ZERO(&rtserver->rt_fds); |
---|
31 | |
---|
32 | if (hostname) { |
---|
33 | if ((he=gethostbyname(hostname)) == NULL) { |
---|
34 | perror("gethostbyname"); |
---|
35 | return 0; |
---|
36 | } |
---|
37 | } |
---|
38 | |
---|
39 | if ((rtserver->connect_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { |
---|
40 | perror("socket"); |
---|
41 | return 0; |
---|
42 | } |
---|
43 | if (setsockopt(rtserver->connect_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) { |
---|
44 | perror("setsockopt"); |
---|
45 | return 0; |
---|
46 | } |
---|
47 | rtserver->remote = calloc(1,sizeof(struct sockaddr_in)); |
---|
48 | // Need to set up a listening server here |
---|
49 | bzero((char *) rtserver->remote, sizeof(rtserver->remote)); |
---|
50 | rtserver->remote->sin_family = AF_INET; |
---|
51 | if (hostname) |
---|
52 | rtserver->remote->sin_addr = *((struct in_addr *)he->h_addr); |
---|
53 | else |
---|
54 | rtserver->remote->sin_addr.s_addr = INADDR_ANY; |
---|
55 | rtserver->remote->sin_port = htons(port); |
---|
56 | |
---|
57 | if (bind(rtserver->connect_fd, (struct sockaddr *) rtserver->remote, sizeof(struct sockaddr_in)) < 0) { |
---|
58 | perror("bind"); |
---|
59 | return 0; |
---|
60 | } |
---|
61 | |
---|
62 | if (listen(rtserver->connect_fd, 10) == -1) { |
---|
63 | perror("listen"); |
---|
64 | return 0; |
---|
65 | } |
---|
66 | |
---|
67 | rtserver->max_rtfds = rtserver->connect_fd; |
---|
68 | |
---|
69 | return rtserver; |
---|
70 | } |
---|
71 | |
---|
72 | void rtserver_destroy (struct rtserver_t * rtserver) { |
---|
73 | int i; |
---|
74 | close(rtserver->connect_fd); |
---|
75 | |
---|
76 | for (i=1; i <= rtserver->max_rtfds; i++) { |
---|
77 | if (FD_ISSET(i, &rtserver->rt_fds)) { |
---|
78 | close(i); |
---|
79 | } |
---|
80 | } |
---|
81 | |
---|
82 | free(rtserver->remote); |
---|
83 | free(rtserver); |
---|
84 | } |
---|
85 | |
---|
86 | int rtserver_checklisten (struct rtserver_t * rtserver) { |
---|
87 | struct timeval tv; |
---|
88 | int rt_fd = 0; |
---|
89 | fd_set current; |
---|
90 | int i; |
---|
91 | int sin_size = sizeof(struct sockaddr_in); |
---|
92 | |
---|
93 | tv.tv_sec = 0; |
---|
94 | tv.tv_usec = 0; |
---|
95 | |
---|
96 | FD_ZERO(¤t); |
---|
97 | FD_SET(rtserver->connect_fd, ¤t); |
---|
98 | |
---|
99 | do { |
---|
100 | if (select(rtserver->max_rtfds + 1, ¤t, NULL, NULL,&tv) >=0 ) { |
---|
101 | break; |
---|
102 | } |
---|
103 | } |
---|
104 | while (errno == EINTR); |
---|
105 | for (i = 0; i <= rtserver->max_rtfds; i++) { |
---|
106 | if (FD_ISSET(i, ¤t)) { |
---|
107 | // Got something on the listening socket |
---|
108 | if (i == rtserver->connect_fd) { |
---|
109 | if ((rt_fd = accept(i, (struct sockaddr *) rtserver->remote, |
---|
110 | &sin_size)) == -1) { |
---|
111 | perror("accept"); |
---|
112 | return -1; |
---|
113 | } else { |
---|
114 | printf("Client connected\n"); |
---|
115 | FD_SET(rt_fd, &rtserver->rt_fds); |
---|
116 | if (rt_fd > rtserver->max_rtfds) |
---|
117 | rtserver->max_rtfds = rt_fd; |
---|
118 | } |
---|
119 | } |
---|
120 | } |
---|
121 | } |
---|
122 | return rt_fd; |
---|
123 | } |
---|
124 | |
---|
125 | int rtserver_sendclients (struct rtserver_t * rtserver, char * buffer, size_t len) { |
---|
126 | fd_set current; |
---|
127 | int i; |
---|
128 | int numbytes = 0; |
---|
129 | struct timeval tv; |
---|
130 | |
---|
131 | tv.tv_sec = 0; |
---|
132 | tv.tv_usec = 0; |
---|
133 | current = rtserver->rt_fds; |
---|
134 | |
---|
135 | if (select(rtserver->max_rtfds + 1, NULL, ¤t, NULL, &tv) == -1 ) { |
---|
136 | perror("select"); |
---|
137 | return -1; |
---|
138 | |
---|
139 | } |
---|
140 | |
---|
141 | // Send the data to each ready client |
---|
142 | for (i = 0; i <= rtserver->max_rtfds; i++) { |
---|
143 | if (FD_ISSET(i, ¤t)) { |
---|
144 | |
---|
145 | // do write |
---|
146 | #ifndef MSG_NOSIGNAL |
---|
147 | #define MSG_NOSIGNAL 0 |
---|
148 | #endif |
---|
149 | |
---|
150 | if ((numbytes = send(i, buffer, len, MSG_NOSIGNAL)) == -1) { |
---|
151 | perror("send"); |
---|
152 | FD_CLR(i, &rtserver->rt_fds); |
---|
153 | close(i); |
---|
154 | numbytes = 0; |
---|
155 | } |
---|
156 | } |
---|
157 | } |
---|
158 | return numbytes; |
---|
159 | } |
---|