47bf7d970f35312400b89a08f5552a2b9efa735e
[blender-staging.git] / extern / verse / dist / v_network.c
1 /*
2 **
3 */
4
5 #if defined _WIN32
6 #include <winsock.h>
7 typedef unsigned int uint;
8 typedef SOCKET VSocket;
9 #else
10 typedef int VSocket;
11 #include <fcntl.h>
12 #include <netdb.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <errno.h>
17 #include <string.h>
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <sys/time.h>
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
23 #include <sys/wait.h>
24 #include <signal.h>
25 #endif
26 #include <stdio.h>
27 #include <stdlib.h>
28
29 typedef unsigned int uint32;
30 typedef int int32;
31 typedef unsigned short uint16;
32 typedef short int16;
33 typedef unsigned char uint8;
34 typedef char int8;
35 typedef char boolean;
36
37 #include "v_cmd_gen.h"
38 #include "v_network.h"
39
40 #define TRUE    1
41 #define FALSE   0
42
43 typedef struct{
44         struct sockaddr_in address;
45         struct hostent *he;
46 } VNetworkConnection;
47
48 #define VERSE_STD_CONNECT_TO_PORT 4950
49
50 static VSocket  my_socket = -1;
51 static uint16   my_port = 0;
52
53 void v_n_set_port(unsigned short port)
54 {
55         my_port = port;
56 }
57
58 VSocket v_n_socket_create(void)
59 {
60         static boolean initialized = FALSE;
61         struct sockaddr_in address;
62         int buffer_size = 1 << 20;
63
64         if(my_socket != -1)
65                 return my_socket;
66 #if defined _WIN32
67         if(!initialized)
68         {
69                 WSADATA wsaData;
70
71                 if(WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
72                 {
73                         fprintf(stderr, "WSAStartup failed.\n");
74                         exit(1);
75                 }
76
77         }
78 #endif
79         initialized = TRUE;
80         if((my_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
81                 return -1;
82 #if defined _WIN32
83         {
84                 unsigned long   one = 1UL;
85                 if(ioctlsocket(my_socket, FIONBIO, &one) != 0)
86                         return -1;
87         }
88 #else
89         if(fcntl(my_socket, F_SETFL, O_NONBLOCK) != 0)
90         {
91                 fprintf(stderr, "v_network: Couldn't make socket non-blocking\n");
92                 return -1;
93         }
94 #endif
95         address.sin_family = AF_INET;     /* host byte order */
96         address.sin_port = htons(my_port); /* short, network byte order */
97         address.sin_addr.s_addr = INADDR_ANY;
98         if(bind(my_socket, (struct sockaddr *) &address, sizeof(struct sockaddr)) != 0)
99         {
100                 fprintf(stderr, "v_network: Failed to bind(), code %d (%s)\n", errno, strerror(errno));
101                 exit(0); /* FIX ME */
102         }
103         if(setsockopt(my_socket, SOL_SOCKET, SO_SNDBUF, (const char *) &buffer_size, sizeof buffer_size) != 0)
104                 fprintf(stderr, "v_network: Couldn't set send buffer size of socket to %d\n", buffer_size);
105         if(setsockopt(my_socket, SOL_SOCKET, SO_RCVBUF, (const char *) &buffer_size, sizeof buffer_size) != 0)
106                 fprintf(stderr, "v_network: Couldn't set receive buffer size of socket to %d\n", buffer_size);
107         return my_socket;
108 }
109
110 void v_n_socket_destroy(void)
111 {
112 #if defined _WIN32
113         closesocket(my_socket);
114 #else
115         close(my_socket);
116 #endif
117         my_socket = -1;
118 }
119
120 boolean v_n_set_network_address(VNetworkAddress *address, const char *host_name)
121 {
122         struct hostent  *he;
123         char            *colon = NULL, *buf = NULL;
124         boolean         ok = FALSE;
125
126         v_n_socket_create();
127         address->port = VERSE_STD_CONNECT_TO_PORT;
128         /* If a port number is included, as indicated by a colon, we need to work a bit more. */
129         if((colon = strchr(host_name, ':')) != NULL)
130         {
131                 size_t  hl = strlen(host_name);
132
133                 if((buf = malloc(hl + 1)) != NULL)
134                 {
135                         unsigned int    tp;
136
137                         strcpy(buf, host_name);
138                         colon = buf + (colon - host_name);
139                         *colon = '\0';
140                         host_name = buf;
141                         if(sscanf(colon + 1, "%u", &tp) == 1)
142                         {
143                                 address->port = (unsigned short) tp;
144                                 if(address->port != tp) /* Protect against overflow. */
145                                         host_name = NULL;
146                         }
147                         else
148                                 host_name = NULL;       /* Protect against parse error. */
149                 }
150                 else
151                         return FALSE;
152         }
153         if(host_name != NULL && (he = gethostbyname(host_name)) != NULL)
154         {
155                 memcpy(&address->ip, he->h_addr_list[0], he->h_length);
156                 address->ip = ntohl(address->ip);
157                 ok = TRUE;
158         }
159         if(buf != NULL)
160                 free(buf);
161
162         return ok;
163 }
164
165 int v_n_send_data(VNetworkAddress *address, const char *data, size_t length)
166 {
167         struct sockaddr_in      address_in;
168         VSocket                 sock;
169         int                     ret;
170
171         if((sock = v_n_socket_create()) == -1 || length == 0)
172                 return 0;
173         address_in.sin_family = AF_INET;     /* host byte order */
174         address_in.sin_port = htons(address->port); /* short, network byte order */
175         address_in.sin_addr.s_addr = htonl(address->ip);
176         memset(&address_in.sin_zero, 0, sizeof address_in.sin_zero);
177         ret = sendto(sock, data, length, 0, (struct sockaddr *) &address_in, sizeof(struct sockaddr_in));
178         if(ret < 0)
179                 fprintf(stderr, "Socket sendto() of %u bytes failed, code %d (%s)\n", (unsigned int) length, errno, strerror(errno));
180         return ret;
181 }
182
183 #if !defined V_GENERATE_FUNC_MODE
184
185 extern void *v_con_get_network_address_id(unsigned int id);
186 extern unsigned int v_con_get_network_address_count();
187
188 unsigned int v_n_wait_for_incoming(unsigned int microseconds) 
189 {
190         struct timeval  tv;
191         fd_set          fd_select;
192         unsigned int    s1, f1, s2, f2;
193
194         if(microseconds == 0)
195                 return 0;
196         v_n_socket_create();
197         tv.tv_sec  = microseconds / 1000000;
198         tv.tv_usec = microseconds % 1000000;
199         FD_ZERO(&fd_select);
200         FD_SET(my_socket, &fd_select);
201         v_n_get_current_time(&s1, &f1);
202         select(1, &fd_select, NULL, NULL, &tv);
203         v_n_get_current_time(&s2, &f2);
204         return (unsigned int) (1000000 * (s2 - s1) + (1000000.0 / 0xffffffffu) * (long) (f2 - f1));     /* Must cast to (long) for f1 > f2 case! */
205 }
206
207 #endif
208
209 int v_n_receive_data(VNetworkAddress *address, char *data, size_t length)
210 {
211         struct  sockaddr_in address_in;
212         size_t  from_length = sizeof address_in, len;
213
214         if(v_n_socket_create() == -1)
215                 return 0;
216         memset(&address_in, 0, sizeof address_in);
217         address_in.sin_family = AF_INET;
218         address_in.sin_port = htons(my_port); 
219         address_in.sin_addr.s_addr = INADDR_ANY;
220         len = recvfrom(v_n_socket_create(), data, length, 0, (struct sockaddr *) &address_in, &from_length);
221         if(len > 0)
222         {
223                 address->ip   = ntohl(address_in.sin_addr.s_addr);
224                 address->port = ntohs(address_in.sin_port);
225         }
226         return len;
227 }
228
229 #if defined _WIN32
230
231 void v_n_get_current_time(uint32 *seconds, uint32 *fractions)
232 {
233         static LARGE_INTEGER frequency;
234         static boolean init = FALSE;
235         LARGE_INTEGER counter;
236
237         if(!init)
238         {
239                 init = TRUE;
240                 QueryPerformanceFrequency(&frequency);
241         }
242
243         QueryPerformanceCounter(&counter);
244         if(seconds != NULL)
245                 *seconds = (uint32) (counter.QuadPart / frequency.QuadPart);
246         if(fractions != NULL)
247                 *fractions = (uint32) ((0xffffffffUL * (counter.QuadPart % frequency.QuadPart)) / frequency.QuadPart);
248 }
249
250 #else
251
252 void v_n_get_current_time(uint32 *seconds, uint32 *fractions)
253 {
254         struct timeval tv;
255
256         gettimeofday(&tv, NULL);
257         if(seconds != NULL)
258             *seconds = tv.tv_sec;
259         if(fractions != NULL)
260                 *fractions = tv.tv_usec * 1E-6 * (double) (uint32)~0;
261 }
262
263 #endif
264
265 void v_n_get_address_string(const VNetworkAddress *address, char *string)
266 {
267         sprintf(string, "%u.%u.%u.%u:%u", address->ip >> 24, (address->ip >> 16) & 0xff,
268                 (address->ip >> 8) & 0xff, address->ip & 0xff, address->port);
269 }