Did some stuff
[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
10
11
12
13 int Network_get_port(int sfd)
14 {
15         static struct sockaddr_in sin;
16         static socklen_t len = sizeof(struct sockaddr_in);
17
18         if (getsockname(sfd, (struct sockaddr *)&sin, &len) != 0)
19                  error("Network_port", "getsockname : %s", strerror(errno));
20         return ntohs(sin.sin_port);
21 }
22
23 int Network_server_bind(int port, int * bound)
24 {
25         int sfd = socket(PF_INET, SOCK_STREAM, 0);
26         if (sfd < 0)
27         {
28                 error("Network_server", "Creating socket on port %d : %s", port, strerror(errno));
29         }
30
31         struct   sockaddr_in name;
32
33         name.sin_family = AF_INET;
34         name.sin_addr.s_addr = htonl(INADDR_ANY);
35         name.sin_port = htons(port);
36
37         if (bind( sfd, (struct sockaddr *) &name, sizeof(name) ) < 0)
38         {
39                 error("Network_server", "Binding socket on port %d : %s", port, strerror(errno));
40         }
41
42         if (bound != NULL)
43                 *bound = Network_get_port(sfd);
44         return sfd;     
45 }
46
47 int Network_server_listen(int sfd, char * addr)
48 {
49         int port = Network_get_port(sfd);
50         if (listen(sfd, 1) < 0)
51         {
52                 error("Network_server", "Listening on port %d : %s", port, strerror(errno));
53         }
54         
55         int psd;
56         if (addr == NULL)
57                 psd = accept(sfd, 0, 0);
58         else
59         {
60                 struct  sockaddr_in client;
61                 struct  hostent *hp;
62
63                 client.sin_family = AF_INET;
64                 hp = gethostbyname(addr);
65                 bcopy ( hp->h_addr, &(client.sin_addr.s_addr), hp->h_length);
66                 client.sin_port = htons(port);
67                 socklen_t len = sizeof(client);
68
69                 psd = accept(sfd, (struct sockaddr*)&client, &len);
70         }
71         close(sfd);
72         sfd = psd;
73         assert(sfd >= 0);
74
75         return sfd;
76 }
77
78 int Network_server(char * addr, int port)
79 {
80         return Network_server_listen(Network_server_bind(port, &port), addr);
81 }
82
83 int Network_client(const char * addr, int port, int timeout)
84 {
85         int sfd = socket(PF_INET, SOCK_STREAM, 0);
86
87         //log_print(2, "Network_client", "Created socket");
88         long arg = fcntl(sfd, F_GETFL, NULL);
89         arg |= O_NONBLOCK;
90         fcntl(sfd, F_SETFL, arg);
91
92         if (sfd < 0)
93         {
94                 error("Network_client", "Creating socket for address %s:%d : %s", addr, port, strerror(errno));
95         }
96         struct  sockaddr_in server;
97         struct  hostent *hp;
98
99
100         server.sin_family = AF_INET;
101         hp = gethostbyname(addr);
102         bcopy ( hp->h_addr, &(server.sin_addr.s_addr), hp->h_length);
103         server.sin_port = htons(port);
104
105
106         int res = connect(sfd, (struct sockaddr *) &server, sizeof(server));
107         
108
109         if (res < 0 && errno == EINPROGRESS)
110         {
111                 
112                 fd_set writeSet;
113                 FD_ZERO(&writeSet);
114                 FD_SET(sfd, &writeSet);
115
116                 struct timeval tv;
117                 tv.tv_sec = timeout;
118                 tv.tv_usec = 0;
119
120                 struct timeval * tp;
121                 tp = (timeout < 0) ? NULL : &tv;
122                 
123                 int err = select(sfd+1, NULL, &writeSet, NULL, tp);
124                 
125                 if (err == 0)
126                 {
127                         error("Network_client", "Timed out trying to connect to %s:%d after %d seconds", addr, port, timeout);
128                 }
129                 else if (err < 0)
130                 {
131                         error("Network_client", "Connecting to %s:%d - Error in select(2) call : %s", addr, port, strerror(errno));
132                 }
133                 else if (FD_ISSET(sfd, &writeSet))
134                 {
135                         int so_error;
136                         socklen_t len = sizeof so_error;
137                         getsockopt(sfd, SOL_SOCKET, SO_ERROR, &so_error, &len);
138                         if (so_error != 0)
139                         {
140                                 error("Network_client", "Connecting to %s:%d : %s", addr, port, strerror(so_error));
141                         }
142                 }
143                 else
144                 {
145                         error("Network_client", "select(2) returned %d but the socket is not writable!?", err);
146                 }
147         }
148         else
149         {
150                 error("Network_client", "Connecting to %s:%d : %s", addr, port, strerror(errno));
151         }
152
153         arg = fcntl(sfd, F_GETFL, NULL);
154         arg &= (~O_NONBLOCK);
155         fcntl(sfd, F_SETFL, arg);
156         
157         
158         
159         return sfd;
160 }
161
162 void Network_close(int sfd)
163 {
164         if (shutdown(sfd, 2) != 0)
165         {
166                 error("Network_close", "Closing socket : %s", strerror(errno));
167         }
168         close(sfd);
169 }

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