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