1 /*
2 * net_socket.c - low level functions to network communication
3 *
4 * $Id: net_socket.c,v 1.10 2006/03/28 11:41:19 fzago Exp $
5 *
6 * Program XBLAST
7 * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2; or (at your option)
12 * any later version
13 *
14 * This program is distributed in the hope that it will be entertaining,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17 * Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #include "xblast.h"
25
26 /* make sure that port range defines are in place */
27 #ifndef USER_MINPORT
28 #define USER_MINPORT 0
29 #endif
30 #ifndef USER_MAXPORT
31 #define USER_MAXPORT 0
32 #endif
33
34 /*
35 * close and delete socket structure
36 */
37 void
Net_Close(XBSocket * pSocket)38 Net_Close (XBSocket * pSocket)
39 {
40 assert (NULL != pSocket);
41 Socket_Close (pSocket);
42 Socket_Free (pSocket);
43 } /* Net_Close */
44
45 /*
46 * bind a socket to a user port on given interface
47 */
48 static XBBool
Net_BindUserPort(XBSocket * pSocket,const char * localname)49 Net_BindUserPort (XBSocket * pSocket, const char *localname)
50 {
51 unsigned short port;
52 /* make sure user requests a port range */
53 assert (USER_MINPORT < USER_MAXPORT);
54 /* find a free port */
55 for (port = USER_MINPORT; port <= USER_MAXPORT; port++) {
56 if (Socket_SetAddressInet (pSocket, XBFalse, localname, port) && Socket_Bind (pSocket)) {
57 return XBTrue;
58 }
59 }
60 Dbg_Out ("NET: failed to bind to user port range\n");
61 return XBFalse;
62 } /* Net_BindUserPort */
63
64 /*
65 * try to connect to server (via TCP/IP)
66 */
67 XBSocket *
Net_ConnectInet(const char * hostName,unsigned short port)68 Net_ConnectInet (const char *hostName, unsigned short port)
69 {
70 XBSocket *pSocket = NULL;
71
72 /* create socket structure */
73 pSocket = Socket_Alloc (AF_INET);
74 /* create socket */
75 if (!Socket_Open (pSocket, SOCK_STREAM)) {
76 goto Error;
77 }
78 if (!Socket_SetAddressInet (pSocket, XBTrue, hostName, port)) {
79 goto Error;
80 }
81 /* bind to user port range locally, if requested */
82 if (USER_MINPORT < USER_MAXPORT && !Net_BindUserPort (pSocket, NULL)) {
83 goto Error;
84 }
85 /* now try to connect */
86 if (!Socket_Connect (pSocket)) {
87 goto Error;
88 }
89 /* that's all */
90 return pSocket;
91 /*
92 * Error handling
93 */
94 Error:
95 Net_Close (pSocket);
96 return NULL;
97 } /* Net_ConnectInet */
98
99 /*
100 * listen for client to connect
101 */
102 XBSocket *
Net_ListenInet(unsigned short port)103 Net_ListenInet (unsigned short port)
104 {
105 XBSocket *pSocket = NULL;
106
107 /* alloc socket data structure */
108 pSocket = Socket_Alloc (AF_INET);
109 /* create socket */
110 if (!Socket_Open (pSocket, SOCK_STREAM)) {
111 goto Error;
112 }
113 /* set socket address structure */
114 if (!Socket_SetAddressInet (pSocket, XBFalse, NULL, port)) {
115 goto Error;
116 }
117 /* enable reuse */
118 if (!Socket_SetReuse (pSocket)) {
119 goto Error;
120 }
121 /* bind to set address */
122 if (!Socket_Bind (pSocket)) {
123 goto Error;
124 }
125 /* now activate listen socket */
126 if (!Socket_Listen (pSocket)) {
127 goto Error;
128 }
129 /* that's all */
130 return pSocket;
131 /*
132 * Error handling
133 */
134 Error:
135 Net_Close (pSocket);
136 return NULL;
137 } /* Net_ListenInet */
138
139 /*
140 * accept client connection
141 */
142 XBSocket *
Net_Accept(const XBSocket * pListen)143 Net_Accept (const XBSocket * pListen)
144 {
145 XBSocket *pSocket;
146
147 /* alloc Socket data structure */
148 pSocket = Socket_Alloc (Socket_Family (pListen));
149 assert (pSocket != NULL);
150 /* try to accept client */
151 if (!Socket_Accept (pSocket, pListen)) {
152 goto Error;
153 }
154 /* that's all */
155 return pSocket;
156 /*
157 * Error handling
158 */
159 Error:
160 Net_Close (pSocket);
161 return NULL;
162 } /* Net_AcceptInet */
163
164 /*
165 * create datagram socket for host
166 */
167 XBSocket *
Net_BindUdp(const char * localname,unsigned port)168 Net_BindUdp (const char *localname, unsigned port)
169 {
170 XBSocket *pSocket;
171
172 /* create socket structure */
173 pSocket = Socket_Alloc (AF_INET);
174 assert (pSocket != NULL);
175 /* create socket */
176 if (!Socket_Open (pSocket, SOCK_DGRAM)) {
177 goto Error;
178 }
179 /* bind socket */
180 if (USER_MINPORT < USER_MAXPORT && port == 0) {
181 /* any port, use user port range */
182 if (!Net_BindUserPort (pSocket, localname)) {
183 goto Error;
184 }
185 }
186 else {
187 /* bind with given port, let system choose, if necessary */
188 if (!Socket_SetAddressInet (pSocket, XBFalse, localname, port)) {
189 goto Error;
190 }
191 if (!Socket_Bind (pSocket)) {
192 goto Error;
193 }
194 }
195 /* that's all */
196 return pSocket;
197 /*
198 * Error handling
199 */
200 Error:
201 Net_Close (pSocket);
202 return NULL;
203 } /* Net_BindInet */
204
205 /*
206 * connect datagram socket to port
207 */
208 XBBool
Net_ConnectUdp(XBSocket * pSocket,const char * hostName,unsigned short port)209 Net_ConnectUdp (XBSocket * pSocket, const char *hostName, unsigned short port)
210 {
211 /* set it */
212 if (!Socket_SetAddressInet (pSocket, XBTrue, hostName, port)) {
213 return XBFalse;
214 }
215 /* now try to connect */
216 if (!Socket_Connect (pSocket)) {
217 return XBFalse;
218 }
219 return XBTrue;
220 } /* Net_ConnectUdp */
221
222 /*
223 * get local host name of socket
224 */
225 const char *
Net_LocalName(const XBSocket * pSocket)226 Net_LocalName (const XBSocket * pSocket)
227 {
228 const char *name;
229 static char hostName[32];
230
231 assert (pSocket != NULL);
232 if (NULL == (name = Socket_HostName (pSocket, XBFalse))) {
233 return NULL;
234 }
235 assert (sizeof (hostName) > strlen (name));
236 strcpy (hostName, name);
237 return hostName;
238 } /* Net_Hostname */
239
240 /*
241 * get remote host name of socket
242 */
243 const char *
Net_RemoteName(const XBSocket * pSocket)244 Net_RemoteName (const XBSocket * pSocket)
245 {
246 const char *name;
247 static char hostName[32];
248
249 assert (pSocket != NULL);
250 if (NULL == (name = Socket_HostName (pSocket, XBTrue))) {
251 return NULL;
252 }
253 assert (sizeof (hostName) > strlen (name));
254 strcpy (hostName, name);
255 return hostName;
256 } /* Net_RemoteName */
257
258 /*
259 * get local port of socket
260 */
261 unsigned
Net_LocalPort(const XBSocket * pSocket)262 Net_LocalPort (const XBSocket * pSocket)
263 {
264 assert (pSocket != NULL);
265 return Socket_HostPort (pSocket, XBFalse);
266 } /* Net_LocalPort */
267
268 /*
269 * get remote port of socket
270 */
271 unsigned
Net_RemotePort(const XBSocket * pSocket)272 Net_RemotePort (const XBSocket * pSocket)
273 {
274 assert (pSocket != NULL);
275 return Socket_HostPort (pSocket, XBTrue);
276 } /* Net_RemotePort */
277
278 /*
279 * end of file net_socket.c
280 */
281