Forgot Makefile
[matches/swarm.git] / src / network.c
1 #include "network.h"
2 #include <assert.h>
3 #include <errno.h>
4 #include <sys/select.h>
5 #include "log.h"
6
7 #define h_addr h_addr_list[0]
8
9 int Network_server(int port) {return Network_server_r(NULL, port);}
10
11 int Network_server_r(char * addr, int port)
12 {
13         int sfd = socket(PF_INET, SOCK_STREAM, 0);
14         if (sfd < 0)
15         {
16                 error("Network_server", "Creating socket on port %d : %s", port, strerror(errno));
17         }
18
19         struct   sockaddr_in name;
20
21         name.sin_family = AF_INET;
22         name.sin_addr.s_addr = htonl(INADDR_ANY);
23         name.sin_port = htons(port);
24
25         if (bind( sfd, (struct sockaddr *) &name, sizeof(name) ) < 0)
26         {
27                 error("Network_server", "Binding socket on port %d : %s", port, strerror(errno));
28         }
29         if (listen(sfd, 1) < 0)
30         {
31                 error("Network_server", "Listening on port %d : %s", port, strerror(errno));
32         }
33         
34         int psd;
35         if (addr == NULL)
36                 psd = accept(sfd, 0, 0);
37         else
38         {
39                 struct  sockaddr_in client;
40                 struct  hostent *hp;
41
42                 client.sin_family = AF_INET;
43                 hp = gethostbyname(addr);
44                 bcopy ( hp->h_addr, &(client.sin_addr.s_addr), hp->h_length);
45                 client.sin_port = htons(port);
46                 socklen_t len = sizeof(client);
47
48                 psd = accept(sfd, (struct sockaddr*)&client, &len);
49         }
50         close(sfd);
51         sfd = psd;
52         assert(sfd >= 0);
53
54         return sfd;
55         
56 }
57
58 int Network_client(const char * addr, int port, int timeout)
59 {
60         int sfd = socket(PF_INET, SOCK_STREAM, 0);
61         long arg = fcntl(sfd, F_GETFL, NULL);
62         arg |= O_NONBLOCK;
63         fcntl(sfd, F_SETFL, arg);
64
65         if (sfd < 0)
66         {
67                 error("Network_client", "Creating socket for address %s:%d : %s", addr, port, strerror(errno));
68         }
69         struct  sockaddr_in server;
70         struct  hostent *hp;
71
72
73         server.sin_family = AF_INET;
74         hp = gethostbyname(addr);
75         bcopy ( hp->h_addr, &(server.sin_addr.s_addr), hp->h_length);
76         server.sin_port = htons(port);
77
78         int res = connect(sfd, (struct sockaddr *) &server, sizeof(server));
79         
80
81         if (res < 0 && errno == EINPROGRESS)
82         {
83                 
84                 fd_set writeSet;
85                 FD_ZERO(&writeSet);
86                 FD_SET(sfd, &writeSet);
87
88                 struct timeval tv;
89                 tv.tv_sec = timeout;
90                 tv.tv_usec = 0;
91
92                 struct timeval * tp;
93                 tp = (timeout < 0) ? NULL : &tv;
94         
95                 int err = select(sfd+1, NULL, &writeSet, NULL, tp);
96
97                 if (err == 0)
98                 {
99                         error("Network_client", "Timed out trying to connect to %s:%d after %d seconds", addr, port, timeout);
100                 }
101                 else if (err < 0)
102                 {
103                         error("Network_client", "Connecting to %s:%d - Error in select(2) call : %s", addr, port, strerror(errno));
104                 }
105                 else if (FD_ISSET(sfd, &writeSet))
106                 {
107                         int so_error;
108                         socklen_t len = sizeof so_error;
109                         getsockopt(sfd, SOL_SOCKET, SO_ERROR, &so_error, &len);
110                         if (so_error != 0)
111                         {
112                                 error("Network_client", "Connecting to %s:%d : %s", addr, port, strerror(so_error));
113                         }
114                 }
115                 else
116                 {
117                         error("Network_client", "select(2) returned %d but the socket is not writable!?", err);
118                 }
119         }
120         else
121         {
122                 error("Network_client", "Connecting to %s:%d : %s", addr, port, strerror(errno));
123         }
124
125         arg = fcntl(sfd, F_GETFL, NULL);
126         arg &= (~O_NONBLOCK);
127         fcntl(sfd, F_SETFL, arg);
128         
129
130         return sfd;
131 }
132
133 void Network_close(int sfd)
134 {
135         if (shutdown(sfd, 2) != 0)
136         {
137                 error("Network_close", "Closing socket : %s", strerror(errno));
138         }
139         close(sfd);
140 }

UCC git Repository :: git.ucc.asn.au