on 7afa310 help sign in
Idris-dev/support/network.c
260 lines 5.7 kB history raw
1#include <stdio.h>
2#include <sys/types.h>
3#include <sys/socket.h>
4#include <netinet/in.h>
5#include <arpa/inet.h>
6#include <unistd.h>
7#include <string.h>
8#include <fcntl.h>
9#include <errno.h>
10#include <closure.h>
12#include "network.h"
14int isReadable(int sd, int timeOut) { // milliseconds
15 fd_set socketReadSet;
16 FD_ZERO(&socketReadSet);
17 FD_SET(sd,&socketReadSet);
18 struct timeval tv;
19 if (timeOut) {
20 tv.tv_sec = timeOut / 1000;
21 tv.tv_usec = (timeOut % 1000) * 1000;
22 } else {
23 tv.tv_sec = 0;
24 tv.tv_usec = 0;
25 } // if
26 if (select(sd+1,&socketReadSet,0,0,&tv) == -1) {
27 printf("READ ERROR!\n");
28 return 0;
29 } // if
30 return FD_ISSET(sd,&socketReadSet) != 0;
31} /* isReadable */
33void* net_UDP_clientSocket(char* server, int port) {
34 srand(12345); //time(NULL));
36 Connection* con = (Connection*)EMALLOC(sizeof(Connection));
37 int s;
38 struct sockaddr_in si_me, si_other;
40 if ((s=socket(AF_INET, SOCK_DGRAM, 0))==-1) {
41 printf("FAIL 1\n");
42 return NULL;
43 }
45 memset((char *) &si_other, 0, sizeof(si_other));
46 si_other.sin_family = AF_INET;
47 si_other.sin_port = htons(port);
49 if (inet_aton(server, &si_other.sin_addr)==0) {
50 printf("FAIL 2\n");
51 return NULL;
52 }
54 // Bind, so we can receive replies.
55 si_me.sin_family = AF_INET;
56 si_me.sin_port = htons(0);
57 si_me.sin_addr.s_addr = htonl(INADDR_ANY);
59 if (bind(s, (struct sockaddr*)&si_me, sizeof(si_me))<0) {
60 return NULL;
61 }
63 con->sock = s;
64 con->addr = si_other;
66// printf("Opened client socket %d\n", s);
67 return con;
70void* net_UDP_serverSocket(int port) {
71 srand(time(NULL));
73 Connection* con = (Connection*)EMALLOC(sizeof(Connection));
74 int s;
75 struct sockaddr_in si_me;
77 if ((s=socket(AF_INET, SOCK_DGRAM, 0))==-1) {
78 return NULL;
79 }
81 memset((char *) &si_me, 0, sizeof(si_me));
82 si_me.sin_family = AF_INET;
83 si_me.sin_port = htons(port);
84 si_me.sin_addr.s_addr = htonl(INADDR_ANY);
85 if (bind(s, (struct sockaddr*)&si_me, sizeof(si_me))==-1) {
86 return NULL;
87 }
89 con->sock = s;
90 con->addr = si_me;
92// printf("Opened server socket %d\n", s);
93 return con;
96int net_sendUDP(void* conn, char* server, int port, char* stuff) {
97// printf("Socket is %d\n", conn);
98 if (0) { //rand()%50000 == 0) {
99 printf("DROP\n");
100 return 0;
101 }
104 Connection* c = (Connection*)conn;
105 int s = c->sock;
106 struct sockaddr_in other = c->addr;
107 memset((char *) &other, 0, sizeof(other));
108 other.sin_family = AF_INET;
109 other.sin_port = htons(port);
110 if (inet_aton(server, &other.sin_addr)==0) {
111 printf("FAIL 3\n");
112 return -1;
113 }
115 if (sendto(s, stuff, strlen(stuff), 0, (struct sockaddr*)&other,
116 sizeof(other))==-1) {
117 printf("Send FAIL\n");
118 return -1;
119 }
120// printf("Send WIN, to %s %d %d\n", inet_ntoa(other.sin_addr),
121// ntohs(other.sin_port), port);
122 return 0;
125void* net_recvUDP(void* conn) {
126 struct sockaddr_in other;
127 Connection* c = (Connection*)conn;
128 int s = c->sock;
129 socklen_t slen = sizeof(other);
130 struct sockaddr_in me = c->addr;
132 // TMP HACK: 512 should be enough for the purposes of this experiment...
133 // Do it properly some time.
134 char* buf = (char*)EMALLOC(512*sizeof(char));
136// printf("Waiting to receive\n");
138 int error;
139// while (!isReadable(s,100)) printf(".");
141 if (!isReadable(s, 1000)) {
142 printf("Nothing\n");
143 return NULL;
144 }
146 if (recvfrom(s, buf, 512, 0, (struct sockaddr *)&other, &slen)==-1) {
147 printf("Nothing\n");
148 return NULL;
149 }
151/* printf("Received %s from %s:UDP%u\n",
152 buf,inet_ntoa(other.sin_addr),
153 ntohs(other.sin_port));
154*/
155 // return a structure with the received value, and where it came from.
156 Recv* r = (Recv*)EMALLOC(sizeof(Recv));
157 r->buf = buf;
158 r->server = inet_ntoa(other.sin_addr);
159 r->port = ntohs(other.sin_port);
161 return (void*)r;
164char* get_recvBuf(void* recv) {
165 return ((Recv*)recv)->buf;
168char* get_recvServer(void* recv) {
169 return ((Recv*)recv)->server;
172int get_recvPort(void* recv) {
173 return ((Recv*)recv)->port;
176int nullPtr(void *ptr) {
177 return ptr==NULL;
180// Just to see if the idris FFI is working, and happily talking to .o files...
181int netTest(char* strTest, int num) {
182 int i;
183 for(i=0;i<num;++i) {
184 printf("%s\n",strTest);
185 }
187 return i;
190void net_sendRaw(void* conn, char* server, int port, VAL pkt)
192 int seq = GETINT(PROJECT(pkt, 0));
193 VAL ty = PROJECT(pkt, 1);
194 int pty;
196 switch(TAG(ty)) {
197 case 0:
198 pty = 0;
199 break;
200 case 1:
201 pty = 1;
202 break;
203 case 2:
204 pty = TAG(PROJECT(ty,0)) + 2;
205 }
207 char* buf = (char*)EMALLOC(512*sizeof(char));
208 sprintf(buf, "%d %d", seq, pty);
210 net_sendUDP(conn, server, port, buf);
213VAL net_recvRaw(void* conn)
215 int seq, pty;
217 void* dat = net_recvUDP(conn);
218 if (dat==NULL) {
219 return CONSTRUCTOR(1,0,NULL); // Nothing
220 }
221 else {
222 char* recvBuf = get_recvBuf(dat);
224 sscanf(recvBuf, "%d %d", &seq, &pty);
225 VAL ptyc = NULL;
226 if (pty<2) {
227 ptyc = CONSTRUCTOR(pty,0,NULL);
228 } else {
229 ptyc = CONSTRUCTOR1(2, CONSTRUCTOR(pty-2,0,NULL));
230 }
231 VAL pkt = CONSTRUCTOR2(0, MKINT(seq), ptyc);
232 printf("Received %d %d\n", seq, pty);
234 VAL recvpkt = CONSTRUCTOR3(0, pkt, MKSTR(get_recvServer(dat)),
235 MKINT(get_recvPort(dat)));
237 return CONSTRUCTOR1(0, recvpkt); // Just pkt
238 }
242void dumpPkt(VAL pkt)
244 int seq = GETINT(PROJECT(pkt, 0));
245 VAL ty = PROJECT(pkt, 1);
246 int pty;
248 switch(TAG(ty)) {
249 case 0:
250 pty = 0;
251 break;
252 case 1:
253 pty = 1;
254 break;
255 case 2:
256 pty = TAG(PROJECT(ty,0)) + 2;
257 }
259 printf("%d %d\n", seq, pty);