add SDL_net source (not ported)

This commit is contained in:
dborth 2009-04-29 07:40:27 +00:00
parent d80f471105
commit 7690bb4d2b
21 changed files with 14860 additions and 0 deletions

65
SDL_net/Makefile Normal file
View file

@ -0,0 +1,65 @@
# Directories.
OBJ_DIR := obj
LIB_DIR := lib
BIN_DIR := bin
SRC_DIR := src
INCLUDE_DIR := include
INSTALL_HEADER_DIR ?= $(DEVKITPRO)/libogc/include
INSTALL_LIB_DIR ?= $(DEVKITPRO)/libogc/lib/wii
# Tools.
PIPE_TO_SED := 2>&1 | sed "s/:\([0-9]*\):/\(\1\) :/"
# Library source files.
SRCS := $(wildcard $(SRC_DIR)/*.c)
# Library object files.
OBJS := $(subst $(SRC_DIR),$(OBJ_DIR),$(SRCS:.c=.o))
# What's a full build?
all: $(LIB_DIR)/libSDL_net.a
# How to delete the intermediate files.
clean:
@echo Cleaning $(LIB_DIR)/libSDL_net.a $(OBJ_DIR)
@rm -f $(LIB_DIR)/libSDL_net.a $(OBJS) $(TEST_OBJS)
install:
lib-install:
@mkdir -p $(INSTALL_HEADER_DIR) $(INSTALL_LIB_DIR)
@mkdir -p $(INSTALL_HEADER_DIR)/SDL
@cp -frv $(LIB_DIR)/*.* $(INSTALL_LIB_DIR)
@cp -frv include/*.* $(INSTALL_HEADER_DIR)/SDL
# How to build a library.
$(LIB_DIR)/libSDL_net.a: $(OBJS)
@echo Archiving $@
@-mkdir -p $(dir $@)
@powerpc-gekko-ar crs $@ $(OBJS)
@echo ----
# How to copy a header file
$(INCLUDE_DIR)/SDL_net.h: $(SRC_DIR)/SDL_net.h
@echo Copy $(SRC_DIR)/SDL_net.h to $(INCLUDE_DIR)
@-mkdir -p $(dir $@)
@cp $(SRC_DIR)/SDL_net.h $(INCLUDE_DIR)
# Compilation flags.
COMMON_FLAGS := -g -O2 -mrvl -Wall $(MACHDEP)
INCLUDES := -Iinclude -I$(DEVKITPRO)/libogc/include -I$(DEVKITPRO)/libogc/include/SDL
# -include sys/wait.h
# -include sys/syslimits.h
DEFINES := -DGEKKO
CFLAGS := $(COMMON_FLAGS) $(INCLUDES) $(DEFINES)
# Test link flags.
LDFLAGS := $(COMMON_FLAGS) -L$(LIB_DIR) -L$(DEVKITPRO)/libogc/lib/wii -lSDL -lfat -lwiiuse -lbte -logc -lm
# How to compile C file (SDL library).
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
@echo Compiling $<
@-mkdir -p $(dir $@)
@powerpc-gekko-gcc $(CFLAGS) -c $< -o $@ $(PIPE_TO_SED)

89
SDL_net/src/CHANGES Normal file
View file

@ -0,0 +1,89 @@
1.2.8:
esigra - Mon Feb 16 20:59:55 PST 2009
* Fixed C++ compilation with -Wold-style-cast
1.2.7:
Matthew Mondor - Fri Jan 4 08:44:22 PST 2008
* Enable multicast receiving on 224.0.0.1 on Windows (already worked on UNIX)
Joakim L. Gilje - Sat Jul 14 22:54:37 PDT 2007
* Set server TCP sockets to blocking mode on Mac OS X, Solaris, etc.
1.2.6:
Sam Lantinga - Sun Apr 30 01:48:40 PDT 2006
* Added gcc-fat.sh for generating Universal binaries on Mac OS X
* Updated libtool support to version 1.5.22
Sam Lantinga - Wed Nov 19 00:23:44 PST 2003
* Updated libtool support for new mingw32 DLL build process
Shard - Thu, 05 Jun 2003 09:30:20 -0500
* Fixed compiling on BeOS, which may not have SO_BROADCAST
Kyle Davenport - Sat, 19 Apr 2003 17:13:31 -0500
* Added .la files to the development RPM, fixing RPM build on RedHat 8
1.2.5:
Luc-Olivier de Charrière - Sun, 05 Jan 2003 22:04:29 +0100
* Added support for sending UDP broadcast packets
Sam Lantinga - Sun Oct 20 20:54:41 PDT 2002
* Added shared library support for MacOS X
Sam Lantinga - Sat Aug 24 18:16:08 PDT 2002
* It is now safe to nest calls to SDLNet_Init() / SDLNet_Quit()
Gaëtan de Menten - Sat Aug 24 18:08:39 PDT 2002
* Fixed UDP virtual address bind bug
1.2.4:
Sam Lantinga - Sat Apr 13 07:49:47 PDT 2002
* Updated autogen.sh for new versions of automake
* Specify the SDL API calling convention (C by default)
Stephane Magnenat - Wed Feb 13 15:28:04 PST 2002
* Sockets are created with the SO_REUSEADDR flag by default
Juergen Wind - Wed Feb 13 09:21:55 PST 2002
* Fixed data alignment problems on IRIX
1.2.3:
Sam Lantinga - Fri Oct 26 07:15:28 PDT 2001
* Fixed byte order read/write macros on sparc
Jonathan Atkins - Sun Sep 23 10:44:27 PDT 2001
* Fixed non-blocking socket flags on Windows
1.2.2:
Sam Lantinga - Sun Jul 22 16:41:44 PDT 2001
* Added Project Builder projects for building MacOS X framework
Masahiro Minami - Sun, 27 May 2001 02:10:35 +0900
* Added working MacOS Open Transport support
1.2.1:
Sam Lantinga - Tue Apr 17 11:42:13 PDT 2001
* Cleaned up swap function definitions in SDL_net.h
* Added the swap functions back in for binary compatibility
Paul Jenner - Sat, 14 Apr 2001 09:20:38 -0700 (PDT)
* Added support for building RPM directly from tar archive
1.2.0:
Sam Lantinga - Wed Apr 4 12:42:20 PDT 2001
* Synchronized release version with SDL 1.2.0
1.1.2:
Sam Lantinga - Sat Feb 10 16:33:59 PST 2001
* SDL_net works with the sockets API out of the box on MacOS X.
Paul S Jenner - Sun, 4 Feb 2001 03:58:44 -0800 (PST)
* Added an RPM spec file
Patrick Levin - Mon, 8 Jan 2001 23:20:11 +0100
* Fixed non-blocking socket modes on Win32
John Lawrence - Mon, 13 Nov 2000 10:39:48 -0800
* Fixed compile problem with MSVC++ (type casting)
1.1.1:
Sam Lantinga - Sat Jul 1 15:20:51 PDT 2000
* Modified chat example to work with GUIlib 1.1.0
Roy Wood - Fri Jun 30 10:41:05 PDT 2000
* A few MacOS fixes (not yet complete)
1.1.0:
Andreas Umbach - Sat May 27 14:44:06 PDT 2000
* Suggested non-blocking server sockets
* Suggested setting TCP_NODELAY by default
Roy Wood - Sat May 27 14:41:42 PDT 2000
* Ported to MacOS (not yet complete)
1.0.2:
Miguel Angel Blanch - Sat, 22 Apr 2000 23:06:05
* Implemented SDLNet_ResolveIP()

458
SDL_net/src/COPYING Normal file
View file

@ -0,0 +1,458 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS

67
SDL_net/src/Makefile.am Normal file
View file

@ -0,0 +1,67 @@
# Makefile.am for the SDL sample image loading library and viewer
lib_LTLIBRARIES = libSDL_net.la
libSDL_netincludedir = $(includedir)/SDL
libSDL_netinclude_HEADERS = \
SDL_net.h
libSDL_net_la_SOURCES = \
SDLnet.c \
SDLnetTCP.c \
SDLnetUDP.c \
SDLnetselect.c \
SDLnetsys.h
EXTRA_DIST = \
CHANGES \
version.rc \
VisualC.zip \
Xcode.tar.gz \
MPWmake.sea.bin \
Watcom-OS2.zip \
quit.bmp \
scroll_dn.bmp \
scroll_up.bmp \
SDL_net.spec \
SDL_net.spec.in \
gcc-fat.sh \
autogen.sh
if USE_VERSION_RC
libSDL_net_la_LDFLAGS = \
-no-undefined \
-release $(LT_RELEASE) \
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) -Wl,version.o
libSDL_net_la_LIBADD = @INETLIB@
libSDL_net_la_DEPENDENCIES = version.o
else
libSDL_net_la_LDFLAGS = \
-no-undefined \
-release $(LT_RELEASE) \
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
libSDL_net_la_LIBADD = @INETLIB@
endif
%.o : %.rc
$(WINDRES) $< $@
if HAVE_GUI_LIB
EXAMPLES = chat chatd
else
EXAMPLES =
endif
noinst_PROGRAMS = $(EXAMPLES)
chat_SOURCES = chat.cpp chat.h
chat_LDADD = libSDL_net.la -lGUI
chatd_SOURCES = chatd.c
chatd_LDADD = libSDL_net.la
# Rule to build tar-gzipped distribution package
$(PACKAGE)-$(VERSION).tar.gz: distcheck
# Rule to build RPM distribution package
rpm: $(PACKAGE)-$(VERSION).tar.gz
rpmbuild -ta $(PACKAGE)-$(VERSION).tar.gz

27
SDL_net/src/README Normal file
View file

@ -0,0 +1,27 @@
SDL_net 1.2
The latest version of this library is available from:
http://www.libsdl.org/projects/SDL_net/
This is an example portable network library for use with SDL.
It is available under the GNU Library General Public License.
The API can be found in the file SDL_net.h
This library supports UNIX, Windows, MacOS Classic, MacOS X,
BeOS and QNX.
The demo program is a chat client and server.
The chat client requires the sample GUI library available at:
http://www.libsdl.org/projects/GUIlib/
The chat client connects to the server via TCP, registering itself.
The server sends back a list of connected clients, and keeps the
client updated with the status of other clients.
Every line of text from a client is sent via UDP to every other client.
Note that this isn't necessarily how you would want to write a chat
program, but it demonstrates how to use the basic features of the
network library.
Enjoy!
-Sam Lantinga and Roy Wood

444
SDL_net/src/SDL_net.h Normal file
View file

@ -0,0 +1,444 @@
/*
SDL_net: An example cross-platform network library for use with SDL
Copyright (C) 1997-2009 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/* $Id: SDL_net.h 4432 2009-02-17 05:00:51Z slouken $ */
#ifndef _SDL_NET_H
#define _SDL_NET_H
#include "SDL.h"
#include "SDL_endian.h"
#include "SDL_version.h"
#include "begin_code.h"
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
extern "C" {
#endif
/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL
*/
#define SDL_NET_MAJOR_VERSION 1
#define SDL_NET_MINOR_VERSION 2
#define SDL_NET_PATCHLEVEL 7
/* This macro can be used to fill a version structure with the compile-time
* version of the SDL_net library.
*/
#define SDL_NET_VERSION(X) \
{ \
(X)->major = SDL_NET_MAJOR_VERSION; \
(X)->minor = SDL_NET_MINOR_VERSION; \
(X)->patch = SDL_NET_PATCHLEVEL; \
}
/* This function gets the version of the dynamically linked SDL_net library.
it should NOT be used to fill a version structure, instead you should
use the SDL_NET_VERSION() macro.
*/
extern DECLSPEC const SDL_version * SDLCALL SDLNet_Linked_Version(void);
/* Initialize/Cleanup the network API
SDL must be initialized before calls to functions in this library,
because this library uses utility functions from the SDL library.
*/
extern DECLSPEC int SDLCALL SDLNet_Init(void);
extern DECLSPEC void SDLCALL SDLNet_Quit(void);
/***********************************************************************/
/* IPv4 hostname resolution API */
/***********************************************************************/
typedef struct {
Uint32 host; /* 32-bit IPv4 host address */
Uint16 port; /* 16-bit protocol port */
} IPaddress;
/* Resolve a host name and port to an IP address in network form.
If the function succeeds, it will return 0.
If the host couldn't be resolved, the host portion of the returned
address will be INADDR_NONE, and the function will return -1.
If 'host' is NULL, the resolved host will be set to INADDR_ANY.
*/
#ifndef INADDR_ANY
#define INADDR_ANY 0x00000000
#endif
#ifndef INADDR_NONE
#define INADDR_NONE 0xFFFFFFFF
#endif
#ifndef INADDR_BROADCAST
#define INADDR_BROADCAST 0xFFFFFFFF
#endif
extern DECLSPEC int SDLCALL SDLNet_ResolveHost(IPaddress *address, const char *host, Uint16 port);
/* Resolve an ip address to a host name in canonical form.
If the ip couldn't be resolved, this function returns NULL,
otherwise a pointer to a static buffer containing the hostname
is returned. Note that this function is not thread-safe.
*/
extern DECLSPEC const char * SDLCALL SDLNet_ResolveIP(IPaddress *ip);
/***********************************************************************/
/* TCP network API */
/***********************************************************************/
typedef struct _TCPsocket *TCPsocket;
/* Open a TCP network socket
If ip.host is INADDR_NONE or INADDR_ANY, this creates a local server
socket on the given port, otherwise a TCP connection to the remote
host and port is attempted. The address passed in should already be
swapped to network byte order (addresses returned from
SDLNet_ResolveHost() are already in the correct form).
The newly created socket is returned, or NULL if there was an error.
*/
extern DECLSPEC TCPsocket SDLCALL SDLNet_TCP_Open(IPaddress *ip);
/* Accept an incoming connection on the given server socket.
The newly created socket is returned, or NULL if there was an error.
*/
extern DECLSPEC TCPsocket SDLCALL SDLNet_TCP_Accept(TCPsocket server);
/* Get the IP address of the remote system associated with the socket.
If the socket is a server socket, this function returns NULL.
*/
extern DECLSPEC IPaddress * SDLCALL SDLNet_TCP_GetPeerAddress(TCPsocket sock);
/* Send 'len' bytes of 'data' over the non-server socket 'sock'
This function returns the actual amount of data sent. If the return value
is less than the amount of data sent, then either the remote connection was
closed, or an unknown socket error occurred.
*/
extern DECLSPEC int SDLCALL SDLNet_TCP_Send(TCPsocket sock, const void *data,
int len);
/* Receive up to 'maxlen' bytes of data over the non-server socket 'sock',
and store them in the buffer pointed to by 'data'.
This function returns the actual amount of data received. If the return
value is less than or equal to zero, then either the remote connection was
closed, or an unknown socket error occurred.
*/
extern DECLSPEC int SDLCALL SDLNet_TCP_Recv(TCPsocket sock, void *data, int maxlen);
/* Close a TCP network socket */
extern DECLSPEC void SDLCALL SDLNet_TCP_Close(TCPsocket sock);
/***********************************************************************/
/* UDP network API */
/***********************************************************************/
/* The maximum channels on a a UDP socket */
#define SDLNET_MAX_UDPCHANNELS 32
/* The maximum addresses bound to a single UDP socket channel */
#define SDLNET_MAX_UDPADDRESSES 4
typedef struct _UDPsocket *UDPsocket;
typedef struct {
int channel; /* The src/dst channel of the packet */
Uint8 *data; /* The packet data */
int len; /* The length of the packet data */
int maxlen; /* The size of the data buffer */
int status; /* packet status after sending */
IPaddress address; /* The source/dest address of an incoming/outgoing packet */
} UDPpacket;
/* Allocate/resize/free a single UDP packet 'size' bytes long.
The new packet is returned, or NULL if the function ran out of memory.
*/
extern DECLSPEC UDPpacket * SDLCALL SDLNet_AllocPacket(int size);
extern DECLSPEC int SDLCALL SDLNet_ResizePacket(UDPpacket *packet, int newsize);
extern DECLSPEC void SDLCALL SDLNet_FreePacket(UDPpacket *packet);
/* Allocate/Free a UDP packet vector (array of packets) of 'howmany' packets,
each 'size' bytes long.
A pointer to the first packet in the array is returned, or NULL if the
function ran out of memory.
*/
extern DECLSPEC UDPpacket ** SDLCALL SDLNet_AllocPacketV(int howmany, int size);
extern DECLSPEC void SDLCALL SDLNet_FreePacketV(UDPpacket **packetV);
/* Open a UDP network socket
If 'port' is non-zero, the UDP socket is bound to a local port.
The 'port' should be given in native byte order, but is used
internally in network (big endian) byte order, in addresses, etc.
This allows other systems to send to this socket via a known port.
*/
extern DECLSPEC UDPsocket SDLCALL SDLNet_UDP_Open(Uint16 port);
/* Bind the address 'address' to the requested channel on the UDP socket.
If the channel is -1, then the first unbound channel will be bound with
the given address as it's primary address.
If the channel is already bound, this new address will be added to the
list of valid source addresses for packets arriving on the channel.
If the channel is not already bound, then the address becomes the primary
address, to which all outbound packets on the channel are sent.
This function returns the channel which was bound, or -1 on error.
*/
extern DECLSPEC int SDLCALL SDLNet_UDP_Bind(UDPsocket sock, int channel, IPaddress *address);
/* Unbind all addresses from the given channel */
extern DECLSPEC void SDLCALL SDLNet_UDP_Unbind(UDPsocket sock, int channel);
/* Get the primary IP address of the remote system associated with the
socket and channel. If the channel is -1, then the primary IP port
of the UDP socket is returned -- this is only meaningful for sockets
opened with a specific port.
If the channel is not bound and not -1, this function returns NULL.
*/
extern DECLSPEC IPaddress * SDLCALL SDLNet_UDP_GetPeerAddress(UDPsocket sock, int channel);
/* Send a vector of packets to the the channels specified within the packet.
If the channel specified in the packet is -1, the packet will be sent to
the address in the 'src' member of the packet.
Each packet will be updated with the status of the packet after it has
been sent, -1 if the packet send failed.
This function returns the number of packets sent.
*/
extern DECLSPEC int SDLCALL SDLNet_UDP_SendV(UDPsocket sock, UDPpacket **packets, int npackets);
/* Send a single packet to the specified channel.
If the channel specified in the packet is -1, the packet will be sent to
the address in the 'src' member of the packet.
The packet will be updated with the status of the packet after it has
been sent.
This function returns 1 if the packet was sent, or 0 on error.
NOTE:
The maximum size of the packet is limited by the MTU (Maximum Transfer Unit)
of the transport medium. It can be as low as 250 bytes for some PPP links,
and as high as 1500 bytes for ethernet.
*/
extern DECLSPEC int SDLCALL SDLNet_UDP_Send(UDPsocket sock, int channel, UDPpacket *packet);
/* Receive a vector of pending packets from the UDP socket.
The returned packets contain the source address and the channel they arrived
on. If they did not arrive on a bound channel, the the channel will be set
to -1.
The channels are checked in highest to lowest order, so if an address is
bound to multiple channels, the highest channel with the source address
bound will be returned.
This function returns the number of packets read from the network, or -1
on error. This function does not block, so can return 0 packets pending.
*/
extern DECLSPEC int SDLCALL SDLNet_UDP_RecvV(UDPsocket sock, UDPpacket **packets);
/* Receive a single packet from the UDP socket.
The returned packet contains the source address and the channel it arrived
on. If it did not arrive on a bound channel, the the channel will be set
to -1.
The channels are checked in highest to lowest order, so if an address is
bound to multiple channels, the highest channel with the source address
bound will be returned.
This function returns the number of packets read from the network, or -1
on error. This function does not block, so can return 0 packets pending.
*/
extern DECLSPEC int SDLCALL SDLNet_UDP_Recv(UDPsocket sock, UDPpacket *packet);
/* Close a UDP network socket */
extern DECLSPEC void SDLCALL SDLNet_UDP_Close(UDPsocket sock);
/***********************************************************************/
/* Hooks for checking sockets for available data */
/***********************************************************************/
typedef struct _SDLNet_SocketSet *SDLNet_SocketSet;
/* Any network socket can be safely cast to this socket type */
typedef struct {
int ready;
} *SDLNet_GenericSocket;
/* Allocate a socket set for use with SDLNet_CheckSockets()
This returns a socket set for up to 'maxsockets' sockets, or NULL if
the function ran out of memory.
*/
extern DECLSPEC SDLNet_SocketSet SDLCALL SDLNet_AllocSocketSet(int maxsockets);
/* Add a socket to a set of sockets to be checked for available data */
#define SDLNet_TCP_AddSocket(set, sock) \
SDLNet_AddSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock))
#define SDLNet_UDP_AddSocket(set, sock) \
SDLNet_AddSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock))
extern DECLSPEC int SDLCALL SDLNet_AddSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock);
/* Remove a socket from a set of sockets to be checked for available data */
#define SDLNet_TCP_DelSocket(set, sock) \
SDLNet_DelSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock))
#define SDLNet_UDP_DelSocket(set, sock) \
SDLNet_DelSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock))
extern DECLSPEC int SDLCALL SDLNet_DelSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock);
/* This function checks to see if data is available for reading on the
given set of sockets. If 'timeout' is 0, it performs a quick poll,
otherwise the function returns when either data is available for
reading, or the timeout in milliseconds has elapsed, which ever occurs
first. This function returns the number of sockets ready for reading,
or -1 if there was an error with the select() system call.
*/
extern DECLSPEC int SDLCALL SDLNet_CheckSockets(SDLNet_SocketSet set, Uint32 timeout);
/* After calling SDLNet_CheckSockets(), you can use this function on a
socket that was in the socket set, to find out if data is available
for reading.
*/
#define SDLNet_SocketReady(sock) \
((sock != NULL) && SDL_reinterpret_cast(SDLNet_GenericSocket, sock)->ready)
/* Free a set of sockets allocated by SDL_NetAllocSocketSet() */
extern DECLSPEC void SDLCALL SDLNet_FreeSocketSet(SDLNet_SocketSet set);
/***********************************************************************/
/* Platform-independent data conversion functions */
/***********************************************************************/
/* Write a 16/32 bit value to network packet buffer */
extern DECLSPEC void SDLCALL SDLNet_Write16(Uint16 value, void *area);
extern DECLSPEC void SDLCALL SDLNet_Write32(Uint32 value, void *area);
/* Read a 16/32 bit value from network packet buffer */
extern DECLSPEC Uint16 SDLCALL SDLNet_Read16(void *area);
extern DECLSPEC Uint32 SDLCALL SDLNet_Read32(void *area);
/***********************************************************************/
/* Error reporting functions */
/***********************************************************************/
/* We'll use SDL's functions for error reporting */
#define SDLNet_SetError SDL_SetError
#define SDLNet_GetError SDL_GetError
/* I'm eventually going to try to disentangle SDL_net from SDL, thus making
SDL_net an independent X-platform networking toolkit. Not today though....
extern no_parse_DECLSPEC void SDLCALL SDLNet_SetError(const char *fmt, ...);
extern no_parse_DECLSPEC char * SDLCALL SDLNet_GetError(void);
*/
/* Inline macro functions to read/write network data */
/* Warning, some systems have data access alignment restrictions */
#if defined(sparc) || defined(mips)
#define SDL_DATA_ALIGNED 1
#endif
#ifndef SDL_DATA_ALIGNED
#define SDL_DATA_ALIGNED 0
#endif
/* Write a 16 bit value to network packet buffer */
#if !SDL_DATA_ALIGNED
#define SDLNet_Write16(value, areap) \
(*SDL_reinterpret_cast(Uint16 *, areap) = SDL_SwapBE16(value))
#else
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
#define SDLNet_Write16(value, areap) \
do \
{ \
Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \
area[0] = (value >> 8) & 0xFF; \
area[1] = value & 0xFF; \
} while ( 0 )
#else
#define SDLNet_Write16(value, areap) \
do \
{ \
Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \
area[1] = (value >> 8) & 0xFF; \
area[0] = value & 0xFF; \
} while ( 0 )
#endif
#endif /* !SDL_DATA_ALIGNED */
/* Write a 32 bit value to network packet buffer */
#if !SDL_DATA_ALIGNED
#define SDLNet_Write32(value, areap) \
*SDL_reinterpret_cast(Uint32 *, areap) = SDL_SwapBE32(value);
#else
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
#define SDLNet_Write32(value, areap) \
do \
{ \
Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \
area[0] = (value >> 24) & 0xFF; \
area[1] = (value >> 16) & 0xFF; \
area[2] = (value >> 8) & 0xFF; \
area[3] = value & 0xFF; \
} while ( 0 )
#else
#define SDLNet_Write32(value, areap) \
do \
{ \
Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \
area[3] = (value >> 24) & 0xFF; \
area[2] = (value >> 16) & 0xFF; \
area[1] = (value >> 8) & 0xFF; \
area[0] = value & 0xFF; \
} while ( 0 )
#endif
#endif /* !SDL_DATA_ALIGNED */
/* Read a 16 bit value from network packet buffer */
#if !SDL_DATA_ALIGNED
#define SDLNet_Read16(areap) \
(SDL_SwapBE16(*SDL_reinterpret_cast(Uint16 *, areap)))
#else
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
#define SDLNet_Read16(areap) \
(((SDL_reinterpret_cast(Uint8 *, areap))[0] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[1] << 0)
#else
#define SDLNet_Read16(areap) \
(((SDL_reinterpret_cast(Uint8 *, areap))[1] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[0] << 0)
#endif
#endif /* !SDL_DATA_ALIGNED */
/* Read a 32 bit value from network packet buffer */
#if !SDL_DATA_ALIGNED
#define SDLNet_Read32(areap) \
(SDL_SwapBE32(*SDL_reinterpret_cast(Uint32 *, areap)))
#else
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
#define SDLNet_Read32(areap) \
(((SDL_reinterpret_cast(Uint8 *, areap))[0] << 24) | ((SDL_reinterpret_cast(Uint8 *, areap))[1] << 16) | \
((SDL_reinterpret_cast(Uint8 *, areap))[2] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[3] << 0)
#else
#define SDLNet_Read32(areap) \
(((SDL_reinterpret_cast(Uint8 *, areap))[3] << 24) | ((SDL_reinterpret_cast(Uint8 *, areap))[2] << 16) | \
((SDL_reinterpret_cast(Uint8 *, areap))[1] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[0] << 0)
#endif
#endif /* !SDL_DATA_ALIGNED */
#ifdef MACOS_OPENTRANSPORT
#endif
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
#endif
#include "close_code.h"
#endif /* _SDL_NET_H */

View file

@ -0,0 +1,96 @@
<QPG:Generation>
<QPG:Options>
<QPG:User unattended="yes" verbosity="0" listfiles="yes"/>
<QPG:Defaults type="qnx_package"/>
<QPG:Source></QPG:Source>
<QPG:Release date="today" number="+"/>
<QPG:Build></QPG:Build>
<QPG:FileSorting strip="yes"/>
<QPG:Package targets="standart"/>
<QPG:Repository generate="yes"/>
<QPG:FinalDir></QPG:FinalDir>
<QPG:Cleanup></QPG:Cleanup>
</QPG:Options>
<QPG:Responsible>
<QPG:Company>QNX.ORG.RU Community</QPG:Company>
<QPG:Department></QPG:Department>
<QPG:Group></QPG:Group>
<QPG:Team>QNX.ORG.RU Team</QPG:Team>
<QPG:Employee>Mike Gorchak</QPG:Employee>
<QPG:EmailAddress>mike@malva.ua</QPG:EmailAddress>
</QPG:Responsible>
<QPG:Values>
<QPG:Files>
<QPG:Add file="./COPYING" install="LicenseUrl/" handling="repdata"/>
<QPG:Add permissions="0755" file="./.libs/libSDL_net-1.2.so.0" install="/opt/lib/"/>
<QPG:Add filetype="symlink" file="libSDL_net.so" install="/opt/lib/" linkto="libSDL_net-1.2.so.0"/>
<QPG:Add filetype="symlink" file="libSDL_net-1.1.so.0" install="/opt/lib/" linkto="libSDL_net-1.2.so.0"/>
<QPG:Add filetype="symlink" file="libSDL_net-1.0.so.0" install="/opt/lib/" linkto="libSDL_net-1.2.so.0"/>
<QPG:Add permissions="0644" file="./.libs/libSDL_net.a" install="/opt/lib/"/>
<QPG:Add permissions="0644" file="./.libs/libSDL_net.lai" install="/opt/lib/libSDL_net.la"/>
<QPG:Add permissions="0644" file="./SDL_net.h" install="/opt/include/SDL/"/>
<QPG:Add permissions="0644" file="./CHANGES" install="/usr/doc/SDL12_net/"/>
<QPG:Add permissions="0644" file="./COPYING" install="/usr/doc/SDL12_net/"/>
<QPG:Add permissions="0644" file="./README" install="/usr/doc/SDL12_net/"/>
</QPG:Files>
<QPG:PackageFilter>
<QPM:PackageManifest>
<QPM:PackageDescription>
<QPM:PackageType>Library</QPM:PackageType>
<QPM:PackageName>SDL_net</QPM:PackageName>
<QPM:PackageReleaseNumber>1</QPM:PackageReleaseNumber>
<QPM:PackageRepository>http://qnx.org.ru/repository</QPM:PackageRepository>
<QPM:FileVersion>2.0</QPM:FileVersion>
</QPM:PackageDescription>
<QPM:ProductDescription>
<QPM:ProductName>SDL_net</QPM:ProductName>
<QPM:ProductIdentifier>SDL_net</QPM:ProductIdentifier>
<QPM:ProductEmail>slouken@libsdl.org</QPM:ProductEmail>
<QPM:VendorName>public</QPM:VendorName>
<QPM:VendorInstallName>public</QPM:VendorInstallName>
<QPM:VendorURL>http://www.libsdl.org</QPM:VendorURL>
<QPM:VendorEmbedURL/>
<QPM:VendorEmail>slouken@libsdl.org</QPM:VendorEmail>
<QPM:AuthorName>Sam Lantinga</QPM:AuthorName>
<QPM:AuthorURL>http://www.libsdl.org</QPM:AuthorURL>
<QPM:AuthorEmbedURL/>
<QPM:AuthorEmail>slouken@libsdl.org</QPM:AuthorEmail>
<QPM:ProductIconSmall/>
<QPM:ProductIconLarge/>
<QPM:ProductDescriptionShort>SDL_net - is a portable network library for use with SDL.</QPM:ProductDescriptionShort>
<QPM:ProductDescriptionLong>SDL_net - is a portable network library for use with SDL.</QPM:ProductDescriptionLong>
<QPM:ProductDescriptionURL>http://www.libsdl.org</QPM:ProductDescriptionURL>
<QPM:ProductDescriptionEmbedURL/>
</QPM:ProductDescription>
<QPM:ReleaseDescription>
<QPM:ReleaseVersion>@VERSION@</QPM:ReleaseVersion>
<QPM:ReleaseUrgency>High</QPM:ReleaseUrgency>
<QPM:ReleaseStability>Stable</QPM:ReleaseStability>
<QPM:ReleaseNoteMinor/>
<QPM:ReleaseNoteMajor/>
<QPM:ReleaseBuild>1</QPM:ReleaseBuild>
<QPM:CountryExclude/>
<QPM:ReleaseCopyright>GNU General Public License</QPM:ReleaseCopyright>
</QPM:ReleaseDescription>
<QPM:ContentDescription>
<QPM:ContentTopic>Software Development/Libraries and Extensions/C Libraries</QPM:ContentTopic>
<QPM:ContentKeyword>SDL, net, network</QPM:ContentKeyword>
<QPM:Processor/>
<QPM:TargetProcessor/>
<QPM:TargetOS>qnx6</QPM:TargetOS>
<QPM:HostOS>qnx6</QPM:HostOS>
<QPM:DisplayEnvironment>Console</QPM:DisplayEnvironment>
<QPM:TargetAudience>Developer</QPM:TargetAudience>
<QPM:TargetAudience>User</QPM:TargetAudience>
</QPM:ContentDescription>
<QPM:LicenseUrl>repdata://LicenseUrl/COPYING</QPM:LicenseUrl>
<QPM:ProductInstallationDependencies>
<QPM:ProductRequirements/>
</QPM:ProductInstallationDependencies>
</QPM:PackageManifest>
</QPG:PackageFilter>
</QPG:Values>
</QPG:Generation>

View file

@ -0,0 +1,63 @@
%define name @PACKAGE@
%define version @VERSION@
%define release 1
Summary: SDL portable network library
Name: %{name}
Version: %{version}
Release: %{release}
Source0: %{name}-%{version}.tar.gz
URL: http://www.libsdl.org/projects/SDL_net/
License: LGPL
Group: System Environment/Libraries
BuildRoot: /var/tmp/%{name}-buildroot
Prefix: %{_prefix}
Requires: SDL
%description
This is a portable network library for use with SDL.
%package devel
Summary: Libraries and includes to develop SDL networked applications.
Group: Development/Libraries
Requires: %{name}
%description devel
This is a portable network library for use with SDL.
This is the libraries and include files you can use to develop SDL networked applications.
%prep
rm -rf ${RPM_BUILD_ROOT}
%setup -q
%build
CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{prefix} --disable-gui
make
%install
rm -rf $RPM_BUILD_ROOT
make install prefix=$RPM_BUILD_ROOT/%{prefix}
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%doc README CHANGES COPYING
%{prefix}/lib/lib*.so.*
%files devel
%defattr(-,root,root)
%doc README CHANGES COPYING
%{prefix}/lib/lib*.a
%{prefix}/lib/lib*.la
%{prefix}/lib/lib*.so
%{prefix}/include/SDL/
%changelog
* Sat Feb 3 2001 Paul S Jenner <psj@firstlinux.net>
- First spec file based on SDL spec file
# end of file

430
SDL_net/src/SDLnet.c Normal file
View file

@ -0,0 +1,430 @@
/*
SDL_net: An example cross-platform network library for use with SDL
Copyright (C) 1997-2009 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/* $Id: SDLnet.c 4211 2008-12-08 00:27:32Z slouken $ */
#include <string.h>
#include "SDL_endian.h"
#include "SDLnetsys.h"
#include "SDL_net.h"
const SDL_version *SDLNet_Linked_Version(void)
{
static SDL_version linked_version;
SDL_NET_VERSION(&linked_version);
return(&linked_version);
}
/* Since the UNIX/Win32/BeOS code is so different from MacOS,
we'll just have two completely different sections here.
*/
static int SDLNet_started = 0;
#ifdef MACOS_OPENTRANSPORT
#include <Events.h>
typedef struct
{
Uint8 stat;
InetSvcRef dns;
}DNSStatus, *DNSStatusRef;
enum
{
dnsNotReady = 0,
dnsReady = 1,
dnsResolved = 2,
dnsError = 255
};
//static InetSvcRef dns = 0;
static DNSStatus dnsStatus;
Uint32 OTlocalhost = 0;
/* We need a notifier for opening DNS.*/
/* ( 010311 masahiro minami<elsur@aaa.letter.co.jp>) */
static pascal void OpenDNSNotifier(
void* context, OTEventCode code, OTResult result, void* cookie )
{
switch( code )
{
case T_OPENCOMPLETE:
// DNS is ready now.
if( result == kOTNoError )
{
dnsStatus.dns = (InetSvcRef)cookie;
dnsStatus.stat = dnsReady;
}
else
{
SDLNet_SetError("T_DNRSTRINGTOADDRCOMPLETE event returned an error");
dnsStatus.dns = NULL;
dnsStatus.stat = dnsError;
}
break;
case T_DNRSTRINGTOADDRCOMPLETE:
// DNR resolved the name to address
// WORK IN PROGRESS (TODO )
dnsStatus.stat = dnsResolved;
break;
default:
if( result != kOTNoError )
dnsStatus.stat = dnsError;
}
// Is there anything else to be done here ???
// ( 010311 masahiro minami<elsur@aaa.letter.co.jp> )
// (TODO)
}
/* Local functions for initializing and cleaning up the DNS resolver */
static int OpenDNS(void)
{
int retval;
OSStatus status;
retval = 0;
status = OTAsyncOpenInternetServices(
kDefaultInternetServicesPath, 0, OpenDNSNotifier, NULL);
if ( status == noErr ) {
InetInterfaceInfo info;
dnsStatus.stat = dnsNotReady;
while( dnsStatus.stat != dnsError && dnsStatus.dns == NULL)
{
// what's to be done ? Yield ? WaitNextEvent ? or what ?
// ( 010311 masahiro minami<elsur@aaa.letter.co.jp> )
//YieldToAnyThread();
}
/* Get the address of the local system -
What should it be if ethernet is off?
*/
OTInetGetInterfaceInfo(&info, kDefaultInetInterface);
OTlocalhost = info.fAddress;
} else {
SDLNet_SetError("Unable to open DNS handle");
retval = status;
}
return(retval);
}
static void CloseDNS(void)
{
if ( dnsStatus.dns ) {
OTCloseProvider(dnsStatus.dns);
dnsStatus.dns = 0;
dnsStatus.stat = dnsNotReady;
}
OTlocalhost = 0;
}
/* Initialize/Cleanup the network API */
int SDLNet_Init(void)
{
OSStatus status;
int retval;
dnsStatus.stat = dnsNotReady;
dnsStatus.dns = 0;
retval = 0;
if ( ! SDLNet_started ) {
status = InitOpenTransport();
if ( status == noErr ) {
retval = OpenDNS();
if ( retval < 0 ) {
SDLNet_Quit();
}
} else {
SDLNet_SetError("Unable to initialize Open Transport");
retval = status;
}
}
if ( retval == 0 ) {
++SDLNet_started;
}
return(retval);
}
void SDLNet_Quit(void)
{
if ( SDLNet_started == 0 ) {
return;
}
if ( --SDLNet_started == 0 ) {
CloseDNS();
CloseOpenTransport();
}
}
/* Resolve a host name and port to an IP address in network form */
int SDLNet_ResolveHost(IPaddress *address, const char *host, Uint16 port)
{
int retval = 0;
/* Perform the actual host resolution */
if ( host == NULL ) {
address->host = INADDR_ANY;
} else {
/* int a[4];
address->host = INADDR_NONE;
if ( sscanf(host, "%d.%d.%d.%d", a, a+1, a+2, a+3) == 4 ) {
if ( !(a[0] & 0xFFFFFF00) && !(a[1] & 0xFFFFFF00) &&
!(a[2] & 0xFFFFFF00) && !(a[3] & 0xFFFFFF00) ) {
address->host = ((a[0] << 24) |
(a[1] << 16) |
(a[2] << 8) | a[3]);
if ( address->host == 0x7F000001 ) {
address->host = OTlocalhost;
}
}
}
if ( address->host == INADDR_NONE ) {*/
InetHostInfo hinfo;
/* Check for special case - localhost */
if ( strcmp(host, "localhost") == 0 )
return(SDLNet_ResolveHost(address, "127.0.0.1", port));
/* Have OpenTransport resolve the hostname for us */
retval = OTInetStringToAddress(dnsStatus.dns, (char *)host, &hinfo);
if (retval == noErr) {
while( dnsStatus.stat != dnsResolved )
{WaitNextEvent(everyEvent, 0, 1, NULL );}
address->host = hinfo.addrs[0];
}
//}
}
address->port = SDL_SwapBE16(port);
/* Return the status */
return(retval);
}
/* Resolve an ip address to a host name in canonical form.
If the ip couldn't be resolved, this function returns NULL,
otherwise a pointer to a static buffer containing the hostname
is returned. Note that this function is not thread-safe.
*/
/* MacOS implementation by Roy Wood
*/
const char *SDLNet_ResolveIP(IPaddress *ip)
{
if (ip != nil)
{
InetHost theIP;
static InetDomainName theInetDomainName;
OSStatus theOSStatus;
/* Default result will be null string */
theInetDomainName[0] = '\0';
/* Do a reverse DNS lookup */
theIP = ip->host;
theOSStatus = OTInetAddressToName(dnsStatus.dns,theIP,theInetDomainName);
/* If successful, return the result */
if (theOSStatus == kOTNoError)
{
while( dnsStatus.stat != dnsResolved )
{ /*should we yield or what ? */ }
return(theInetDomainName);
}
}
SDLNet_SetError("Can't perform reverse DNS lookup");
return(NULL);
}
#else /* !MACOS_OPENTRANSPORT */
#ifndef __USE_W32_SOCKETS
#include <signal.h>
#endif
/* Initialize/Cleanup the network API */
int SDLNet_Init(void)
{
if ( !SDLNet_started ) {
#ifdef __USE_W32_SOCKETS
/* Start up the windows networking */
WORD version_wanted = MAKEWORD(1,1);
WSADATA wsaData;
if ( WSAStartup(version_wanted, &wsaData) != 0 ) {
SDLNet_SetError("Couldn't initialize Winsock 1.1\n");
return(-1);
}
#else
/* SIGPIPE is generated when a remote socket is closed */
void (*handler)(int);
handler = signal(SIGPIPE, SIG_IGN);
if ( handler != SIG_DFL ) {
signal(SIGPIPE, handler);
}
#endif
}
++SDLNet_started;
return(0);
}
void SDLNet_Quit(void)
{
if ( SDLNet_started == 0 ) {
return;
}
if ( --SDLNet_started == 0 ) {
#ifdef __USE_W32_SOCKETS
/* Clean up windows networking */
if ( WSACleanup() == SOCKET_ERROR ) {
if ( WSAGetLastError() == WSAEINPROGRESS ) {
WSACancelBlockingCall();
WSACleanup();
}
}
#else
/* Restore the SIGPIPE handler */
void (*handler)(int);
handler = signal(SIGPIPE, SIG_DFL);
if ( handler != SIG_IGN ) {
signal(SIGPIPE, handler);
}
#endif
}
}
/* Resolve a host name and port to an IP address in network form */
int SDLNet_ResolveHost(IPaddress *address, const char *host, Uint16 port)
{
int retval = 0;
/* Perform the actual host resolution */
if ( host == NULL ) {
address->host = INADDR_ANY;
} else {
address->host = inet_addr(host);
if ( address->host == INADDR_NONE ) {
struct hostent *hp;
hp = gethostbyname(host);
if ( hp ) {
memcpy(&address->host,hp->h_addr,hp->h_length);
} else {
retval = -1;
}
}
}
address->port = SDL_SwapBE16(port);
/* Return the status */
return(retval);
}
/* Resolve an ip address to a host name in canonical form.
If the ip couldn't be resolved, this function returns NULL,
otherwise a pointer to a static buffer containing the hostname
is returned. Note that this function is not thread-safe.
*/
/* Written by Miguel Angel Blanch.
* Main Programmer of Arianne RPG.
* http://come.to/arianne_rpg
*/
const char *SDLNet_ResolveIP(IPaddress *ip)
{
struct hostent *hp;
hp = gethostbyaddr((char *)&ip->host, 4, AF_INET);
if ( hp != NULL ) {
return hp->h_name;
}
return NULL;
}
#endif /* MACOS_OPENTRANSPORT */
#if !SDL_DATA_ALIGNED /* function versions for binary compatibility */
/* Write a 16 bit value to network packet buffer */
#undef SDLNet_Write16
void SDLNet_Write16(Uint16 value, void *areap)
{
(*(Uint16 *)(areap) = SDL_SwapBE16(value));
}
/* Write a 32 bit value to network packet buffer */
#undef SDLNet_Write32
void SDLNet_Write32(Uint32 value, void *areap)
{
*(Uint32 *)(areap) = SDL_SwapBE32(value);
}
/* Read a 16 bit value from network packet buffer */
#undef SDLNet_Read16
Uint16 SDLNet_Read16(void *areap)
{
return (SDL_SwapBE16(*(Uint16 *)(areap)));
}
/* Read a 32 bit value from network packet buffer */
#undef SDLNet_Read32
Uint32 SDLNet_Read32(void *areap)
{
return (SDL_SwapBE32(*(Uint32 *)(areap)));
}
#endif /* !SDL_DATA_ALIGNED */
#ifdef USE_GUSI_SOCKETS
/* Configure Socket Factories */
void GUSISetupFactories()
{
GUSIwithInetSockets();
}
/* Configure File Devices */
void GUSISetupDevices()
{
return;
}
#endif /* USE_GUSI_SOCKETS */

953
SDL_net/src/SDLnetTCP.c Normal file
View file

@ -0,0 +1,953 @@
/*
SDL_net: An example cross-platform network library for use with SDL
Copyright (C) 1997-2009 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/* $Id: SDLnetTCP.c 4211 2008-12-08 00:27:32Z slouken $ */
#include "SDLnetsys.h"
#include "SDL_net.h"
/* The network API for TCP sockets */
/* Since the UNIX/Win32/BeOS code is so different from MacOS,
we'll just have two completely different sections here.
*/
#ifdef MACOS_OPENTRANSPORT
#include <Events.h>
#include <Threads.h>
#include <OpenTransport.h>
#include <OpenTptInternet.h>
#include <OTDebug.h>
struct _TCPsocket {
int ready;
SOCKET channel;
// These are taken from GUSI interface.
// I'm not sure if it's really necessary here yet
// ( masahiro minami<elsur@aaa.letter.co.jp> )
// ( 01/02/19 )
OTEventCode curEvent;
OTEventCode newEvent;
OTEventCode event;
OTEventCode curCompletion;
OTEventCode newCompletion;
OTEventCode completion;
OSStatus error;
TEndpointInfo info;
Boolean readShutdown;
Boolean writeShutdown;
Boolean connected;
OTConfigurationRef config; // Master configuration. you can clone this.
TCPsocket nextListener;
// ( end of new members --- masahiro minami<elsur@aaa.letter.co.jp>
IPaddress remoteAddress;
IPaddress localAddress;
int sflag;
// Maybe we don't need this---- it's from original SDL_net
// (masahiro minami<elsur@aaa.letter.co.jp>)
// ( 01/02/20 )
int rcvdPassConn;
};
// To be used in WaitNextEvent() here and there....
// (010311 masahiro minami<elsur@aaa.letter.co.jp>)
EventRecord macEvent;
#if TARGET_API_MAC_CARBON
/* for Carbon */
OTNotifyUPP notifier;
#endif
/* Input: ep - endpointref on which to negotiate the option
enableReuseIPMode - desired option setting - true/false
Return: kOTNoError indicates that the option was successfully negotiated
OSStatus is an error if < 0, otherwise, the status field is
returned and is > 0.
IMPORTANT NOTE: The endpoint is assumed to be in synchronous more, otherwise
this code will not function as desired
*/
/*
NOTE: As this version is written async way, we don't use this function...
(010526) masahiro minami<elsur@aaa.letter.co.jp>
*/
/*
OSStatus DoNegotiateIPReuseAddrOption(EndpointRef ep, Boolean enableReuseIPMode)
{
UInt8 buf[kOTFourByteOptionSize]; // define buffer for fourByte Option size
TOption* opt; // option ptr to make items easier to access
TOptMgmt req;
TOptMgmt ret;
OSStatus err;
if (!OTIsSynchronous(ep))
{
return (-1);
}
opt = (TOption*)buf; // set option ptr to buffer
req.opt.buf = buf;
req.opt.len = sizeof(buf);
req.flags = T_NEGOTIATE; // negotiate for option
ret.opt.buf = buf;
ret.opt.maxlen = kOTFourByteOptionSize;
opt->level = INET_IP; // dealing with an IP Level function
opt->name = IP_REUSEADDR;
opt->len = kOTFourByteOptionSize;
opt->status = 0;
*(UInt32*)opt->value = enableReuseIPMode; // set the desired option level, true or false
err = OTOptionManagement(ep, &req, &ret);
// if no error then return the option status value
if (err == kOTNoError)
{
if (opt->status != T_SUCCESS)
err = opt->status;
else
err = kOTNoError;
}
return err;
}
*/
/* A helper function for Mac OpenTransport support*/
// This function is a complete copy from GUSI
// ( masahiro minami<elsur@aaa.letter.co.jp> )
// ( 01/02/19 )
static __inline__ Uint32 CompleteMask(OTEventCode code)
{
return 1 << (code & 0x1F);
}
/* Notifier for async OT calls */
static pascal void AsyncTCPNotifier( TCPsocket sock, OTEventCode code,
OTResult result, void* cookie )
{
#ifdef DEBUG_NET
printf("AsyncTCPNotifier got an event : 0x%8.8x\n", code );
#endif
switch( code & 0x7f000000L)
{
case 0:
sock->newEvent |= code;
result = 0;
break;
case kCOMPLETEEVENT:
if(!(code & 0x00FFFFE0 ))
sock->newCompletion |= CompleteMask( code );
if( code == T_OPENCOMPLETE )
sock->channel = (SOCKET)(cookie);
break;
default:
if( code != kOTProviderWillClose )
result = 0;
}
// Do we need these ???? TODO
// sock->SetAsyncMacError( result );
// sock->Wakeup();
}
/* Retrieve OT event */
// This function is taken from GUSI interface.
// ( 01/02/19 masahiro minami<elsur@aaa.letter.co.jp> )
static void AsyncTCPPopEvent( TCPsocket sock )
{
// Make sure OT calls are not interrupted
// Not sure if we really need this.
OTEnterNotifier( sock->channel );
sock->event |= (sock->curEvent = sock->newEvent );
sock->completion |= ( sock->curCompletion = sock->newCompletion );
sock->newEvent = sock->newCompletion = 0;
OTLeaveNotifier( sock->channel );
if( sock->curEvent & T_UDERR)
{
// We just clear the error.
// Should we feed this back to users ?
// (TODO )
OTRcvUDErr( sock->channel, NULL );
#ifdef DEBUG_NET
printf("AsyncTCPPopEvent T_UDERR recognized");
#endif
}
// Remote is disconnecting...
if( sock->curEvent & ( T_DISCONNECT | T_ORDREL ))
{
sock->readShutdown = true;
}
if( sock->curEvent &T_CONNECT )
{
// Ignore the info of remote (second parameter).
// Shoule we care ?
// (TODO)
OTRcvConnect( sock->channel, NULL );
sock->connected = 1;
}
if( sock->curEvent & T_ORDREL )
{
OTRcvOrderlyDisconnect( sock->channel );
}
if( sock->curEvent & T_DISCONNECT )
{
OTRcvDisconnect( sock->channel, NULL );
}
// Do we need to ?
// (masahiro minami<elsur@aaa.letter.co.jp>)
//YieldToAnyThread();
}
/* Create a new TCPsocket */
// Because TCPsocket structure gets bigger and bigger,
// I think we'd better have a constructor function and delete function.
// ( 01/02/25 masahiro minami<elsur@aaa.letter.co.jp> )
static TCPsocket AsyncTCPNewSocket()
{
TCPsocket sock;
sock = (TCPsocket)malloc(sizeof(*sock));
if ( sock == NULL ) {
SDLNet_SetError("Out of memory");
return NULL;
}
sock->newEvent = 0;
sock->event = 0;
sock->curEvent = 0;
sock->newCompletion = 0;
sock->completion = 0;
sock->curCompletion = 0;
//sock->info = NULL;
sock->readShutdown = sock->writeShutdown = sock->connected = false;
sock->error = 0;
sock->config = NULL;
sock->nextListener = NULL;
sock->sflag = 0;
return sock;
}
// hmmm.... do we need this ???
// ( 01/02/25 masahiro minami<elsur@aaa.letter.co.jp>)
static void AsycnTCPDeleteSocket( TCPsocket sock )
{
SDLNet_TCP_Close( sock );
}
/* Open a TCP network socket
If 'remote' is NULL, this creates a local server socket on the given port,
otherwise a TCP connection to the remote host and port is attempted.
The newly created socket is returned, or NULL if there was an error.
( re-written by masahiro minami<elsur@aaa.letter.co.jp>
Now endpoint is created in Async mode.
01/02/20 )
*/
TCPsocket SDLNet_TCP_Open(IPaddress *ip)
{
EndpointRef dummy = NULL;
TCPsocket sock = AsyncTCPNewSocket();
if( ! sock)
return NULL;
// Determin whether bind locally, or connect to remote
if ( (ip->host != INADDR_NONE) && (ip->host != INADDR_ANY) )
{
// ######## Connect to remote
OTResult stat;
InetAddress inAddr;
TBind bindReq;
// Open endpoint
sock->error = OTAsyncOpenEndpoint(
OTCreateConfiguration(kTCPName), NULL, &(sock->info),
(OTNotifyProcPtr)(AsyncTCPNotifier),
sock );
AsyncTCPPopEvent( sock );
while( !sock->error && !( sock->completion & CompleteMask(T_OPENCOMPLETE)))
{
//SetThreadState( kCurrentThreadID, kReadyThreadState, kNoThreadID );
//YieldToAnyThread();
//WaitNextEvent(everyEvent, &macEvent, 1, NULL);
AsyncTCPPopEvent( sock );
}
if( !sock->channel )
{
SDLNet_SetError("OTAsyncOpenEndpoint failed --- client socket could not be opened");
goto error_return;
}
// Set blocking mode
// I'm not sure if this is a good solution....
// Check out Apple's sample code, OT Virtual Server
// ( 010314 masahiro minami<elsur@aaa.letter.co.jp>)
sock->error = OTSetBlocking( sock->channel );
if( sock->error != kOTNoError )
{
SDLNet_SetError("OTSetBlocking() returned an error");
goto error_return;
}
// Bind the socket
OTInitInetAddress(&inAddr, 0, 0 );
bindReq.addr.len = sizeof( InetAddress );
bindReq.addr.buf = (unsigned char*)&inAddr;
bindReq.qlen = 0;
sock->error = OTBind( sock->channel, &bindReq, NULL );
AsyncTCPPopEvent(sock);
while( !sock->error && !( sock->completion & CompleteMask(T_BINDCOMPLETE)))
{
//YieldToAnyThread();
//WaitNextEvent(everyEvent, &macEvent, 1, NULL);
AsyncTCPPopEvent(sock);
}
switch( stat = OTGetEndpointState( sock->channel ))
{
InetAddress inAddr;
TCall sndCall;
OTResult res;
case T_OUTCON:
SDLNet_SetError("SDLNet_Open() failed -- T_OUTCON");
goto error_return;
break;
case T_IDLE:
sock->readShutdown = false;
sock->writeShutdown = false;
sock->event &=~T_CONNECT;
OTMemzero(&sndCall, sizeof(TCall));
OTInitInetAddress(&inAddr, ip->port, ip->host );
sndCall.addr.len = sizeof(InetAddress);
sndCall.addr.buf = (unsigned char*)&inAddr;
sock->connected = 0;
res = OTConnect( sock->channel, &sndCall, NULL );
AsyncTCPPopEvent(sock);
while( sock->error == kOTNoDataErr || !sock->connected )
AsyncTCPPopEvent(sock);
break;
default:
// What's to be done ? (TODO)
SDLNet_SetError("SDLNet_TCP_Open() failed -- EndpointState not good");
goto error_return;
}
if( !(sock->event & (T_CONNECT|T_DISCONNECT)))
goto error_return;
AsyncTCPPopEvent( sock );
while( !(sock->event & (T_CONNECT|T_DISCONNECT)))
{
AsyncTCPPopEvent( sock );
}
// OTConnect successfull
if( sock->event & T_CONNECT)
{
sock->remoteAddress.host = inAddr.fHost;
sock->remoteAddress.port = inAddr.fPort;
sock->sflag = false;
}
else
{
// OTConnect failed
sock->event &= ~T_DISCONNECT;
goto error_return;
}
}
else
{
// ######## Bind locally
TBind bindReq;
InetAddress inAddr;
// First, get InetInterfaceInfo.
// I don't search for all of them.
// Does that matter ?
sock->error = OTAsyncOpenEndpoint(
OTCreateConfiguration("tilisten, tcp"), NULL, &(sock->info),
(OTNotifyProcPtr)(AsyncTCPNotifier),
sock);
AsyncTCPPopEvent( sock );
while( !sock->error && !( sock->completion & CompleteMask( T_OPENCOMPLETE)))
{
AsyncTCPPopEvent( sock );
}
if( ! sock->channel )
{
SDLNet_SetError("OTAsyncOpenEndpoint failed --- server socket could not be opened");
goto error_return;
}
// Create a master OTConfiguration
sock->config = OTCreateConfiguration(kTCPName);
if( ! sock->config )
{
SDLNet_SetError("Could not create master OTConfiguration");
goto error_return;
}
// Bind the socket
OTInitInetAddress(&inAddr, ip->port, 0 );
inAddr.fAddressType = AF_INET;
bindReq.addr.len = sizeof( InetAddress );
bindReq.addr.buf = (unsigned char*)&inAddr;
bindReq.qlen = 35; // This number is NOT well considered. (TODO)
sock->localAddress.host = inAddr.fHost;
sock->localAddress.port = inAddr.fPort;
sock->sflag = true;
sock->error = OTBind( sock->channel, &bindReq, NULL );
AsyncTCPPopEvent(sock);
while( !sock->error && !( sock->completion & CompleteMask(T_BINDCOMPLETE)))
{
AsyncTCPPopEvent(sock);
}
if( sock->error != kOTNoError )
{
SDLNet_SetError("Could not bind server socket");
goto error_return;
}
if( dummy )
OTCloseProvider( dummy );
}
sock->ready = 0;
return sock;
error_return:
if( dummy )
OTCloseProvider( dummy );
SDLNet_TCP_Close( sock );
return NULL;
}
/* Accept an incoming connection on the given server socket.
The newly created socket is returned, or NULL if there was an error.
*/
TCPsocket SDLNet_TCP_Accept(TCPsocket server)
{
/* Only server sockets can accept */
if ( ! server->sflag ) {
SDLNet_SetError("Only server sockets can accept()");
return(NULL);
}
server->ready = 0;
/* Accept a new TCP connection on a server socket */
{
InetAddress peer;
TCall peerinfo;
TCPsocket sock = NULL;
Boolean mustListen = false;
OTResult err;
memset(&peerinfo, 0, (sizeof peerinfo ));
peerinfo.addr.buf = (Uint8 *) &peer;
peerinfo.addr.maxlen = sizeof(peer);
while( mustListen || !sock )
{
// OTListen
// We do NOT block ---- right thing ? (TODO)
err = OTListen( server->channel, &peerinfo );
if( err )
goto error_return;
else
{
mustListen = false;
sock = AsyncTCPNewSocket();
if( ! sock )
goto error_return;
}
}
if( sock )
{
// OTAsyncOpenEndpoint
server->error = OTAsyncOpenEndpoint( OTCloneConfiguration( server->config ),
NULL, &(sock->info), (OTNotifyProcPtr)AsyncTCPNotifier, sock );
AsyncTCPPopEvent( sock );
while( !sock->error && !( sock->completion & CompleteMask( T_OPENCOMPLETE)))
{
AsyncTCPPopEvent( sock );
}
if( ! sock->channel )
{
mustListen = false;
goto error_return;
}
// OTAccept
server->completion &= ~(CompleteMask(T_ACCEPTCOMPLETE));
server->error = OTAccept( server->channel, sock->channel, &peerinfo );
AsyncTCPPopEvent( server );
while( !(server->completion & CompleteMask(T_ACCEPTCOMPLETE)))
{
AsyncTCPPopEvent( server );
}
switch( server->error )
{
case kOTLookErr:
switch( OTLook(server->channel ))
{
case T_LISTEN:
mustListen = true;
break;
case T_DISCONNECT:
goto error_return;
}
break;
case 0:
sock->nextListener = server->nextListener;
server->nextListener = sock;
sock->remoteAddress.host = peer.fHost;
sock->remoteAddress.port = peer.fPort;
return sock;
// accept successful
break;
default:
free( sock );
}
}
sock->remoteAddress.host = peer.fHost;
sock->remoteAddress.port = peer.fPort;
sock->sflag = 0;
sock->ready = 0;
/* The socket is ready */
return(sock);
// Error; close the socket and return
error_return:
SDLNet_TCP_Close(sock);
return(NULL);
}
}
/* Get the IP address of the remote system associated with the socket.
If the socket is a server socket, this function returns NULL.
*/
IPaddress *SDLNet_TCP_GetPeerAddress(TCPsocket sock)
{
if ( sock->sflag ) {
return(NULL);
}
return(&sock->remoteAddress);
}
/* Send 'len' bytes of 'data' over the non-server socket 'sock'
This function returns the actual amount of data sent. If the return value
is less than the amount of data sent, then either the remote connection was
closed, or an unknown socket error occurred.
*/
int SDLNet_TCP_Send(TCPsocket sock, const void *datap, int len)
{
const Uint8 *data = (const Uint8 *)datap; /* For pointer arithmetic */
int sent, left;
/* Server sockets are for accepting connections only */
if ( sock->sflag ) {
SDLNet_SetError("Server sockets cannot send");
return(-1);
}
/* Keep sending data until it's sent or an error occurs */
left = len;
sent = 0;
errno = 0;
do {
len = OTSnd(sock->channel, (void *)data, left, 0);
if (len == kOTFlowErr)
len = 0;
if ( len > 0 ) {
sent += len;
left -= len;
data += len;
}
// Do we need to ?
// ( masahiro minami<elsur@aaa.letter.co.jp> )
// (TODO)
//WaitNextEvent(everyEvent, &macEvent, 1, NULL);
//AsyncTCPPopEvent(sock);
} while ( (left > 0) && (len > 0) );
return(sent);
}
/* Receive up to 'maxlen' bytes of data over the non-server socket 'sock',
and store them in the buffer pointed to by 'data'.
This function returns the actual amount of data received. If the return
value is less than or equal to zero, then either the remote connection was
closed, or an unknown socket error occurred.
*/
int SDLNet_TCP_Recv(TCPsocket sock, void *data, int maxlen)
{
int len = 0;
OSStatus res;
/* Server sockets are for accepting connections only */
if ( sock->sflag ) {
SDLNet_SetError("Server sockets cannot receive");
return(-1);
}
do
{
res = OTRcv(sock->channel, data, maxlen-len, 0);
if (res > 0) {
len = res;
}
#ifdef DEBUG_NET
if ( res != kOTNoDataErr )
printf("SDLNet_TCP_Recv received ; %d\n", res );
#endif
AsyncTCPPopEvent(sock);
if( res == kOTLookErr )
{
res = OTLook(sock->channel );
continue;
}
} while ( (len == 0) && (res == kOTNoDataErr) );
sock->ready = 0;
if ( len == 0 ) { /* Open Transport error */
#ifdef DEBUG_NET
printf("Open Transport error: %d\n", res);
#endif
return(-1);
}
return(len);
}
/* Close a TCP network socket */
void SDLNet_TCP_Close(TCPsocket sock)
{
if ( sock != NULL ) {
if ( sock->channel != INVALID_SOCKET ) {
//closesocket(sock->channel);
OTSndOrderlyDisconnect( sock->channel );
}
free(sock);
}
}
#else /* !MACOS_OPENTRANSPORT */
struct _TCPsocket {
int ready;
SOCKET channel;
IPaddress remoteAddress;
IPaddress localAddress;
int sflag;
};
/* Open a TCP network socket
If 'remote' is NULL, this creates a local server socket on the given port,
otherwise a TCP connection to the remote host and port is attempted.
The newly created socket is returned, or NULL if there was an error.
*/
TCPsocket SDLNet_TCP_Open(IPaddress *ip)
{
TCPsocket sock;
struct sockaddr_in sock_addr;
/* Allocate a TCP socket structure */
sock = (TCPsocket)malloc(sizeof(*sock));
if ( sock == NULL ) {
SDLNet_SetError("Out of memory");
goto error_return;
}
/* Open the socket */
sock->channel = socket(AF_INET, SOCK_STREAM, 0);
if ( sock->channel == INVALID_SOCKET ) {
SDLNet_SetError("Couldn't create socket");
goto error_return;
}
/* Connect to remote, or bind locally, as appropriate */
if ( (ip->host != INADDR_NONE) && (ip->host != INADDR_ANY) ) {
// ######### Connecting to remote
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
sock_addr.sin_addr.s_addr = ip->host;
sock_addr.sin_port = ip->port;
/* Connect to the remote host */
if ( connect(sock->channel, (struct sockaddr *)&sock_addr,
sizeof(sock_addr)) == SOCKET_ERROR ) {
SDLNet_SetError("Couldn't connect to remote host");
goto error_return;
}
sock->sflag = 0;
} else {
// ########## Binding locally
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
sock_addr.sin_addr.s_addr = INADDR_ANY;
sock_addr.sin_port = ip->port;
/*
* Windows gets bad mojo with SO_REUSEADDR:
* http://www.devolution.com/pipermail/sdl/2005-September/070491.html
* --ryan.
*/
#ifndef WIN32
/* allow local address reuse */
{ int yes = 1;
setsockopt(sock->channel, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes));
}
#endif
/* Bind the socket for listening */
if ( bind(sock->channel, (struct sockaddr *)&sock_addr,
sizeof(sock_addr)) == SOCKET_ERROR ) {
SDLNet_SetError("Couldn't bind to local port");
goto error_return;
}
if ( listen(sock->channel, 5) == SOCKET_ERROR ) {
SDLNet_SetError("Couldn't listen to local port");
goto error_return;
}
/* Set the socket to non-blocking mode for accept() */
#if defined(__BEOS__) && defined(SO_NONBLOCK)
/* On BeOS r5 there is O_NONBLOCK but it's for files only */
{
long b = 1;
setsockopt(sock->channel, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
}
#elif defined(O_NONBLOCK)
{
fcntl(sock->channel, F_SETFL, O_NONBLOCK);
}
#elif defined(WIN32)
{
unsigned long mode = 1;
ioctlsocket (sock->channel, FIONBIO, &mode);
}
#elif defined(__OS2__)
{
int dontblock = 1;
ioctl(sock->channel, FIONBIO, &dontblock);
}
#else
#warning How do we set non-blocking mode on other operating systems?
#endif
sock->sflag = 1;
}
sock->ready = 0;
#ifdef TCP_NODELAY
/* Set the nodelay TCP option for real-time games */
{ int yes = 1;
setsockopt(sock->channel, IPPROTO_TCP, TCP_NODELAY, (char*)&yes, sizeof(yes));
}
#endif /* TCP_NODELAY */
/* Fill in the channel host address */
sock->remoteAddress.host = sock_addr.sin_addr.s_addr;
sock->remoteAddress.port = sock_addr.sin_port;
/* The socket is ready */
return(sock);
error_return:
SDLNet_TCP_Close(sock);
return(NULL);
}
/* Accept an incoming connection on the given server socket.
The newly created socket is returned, or NULL if there was an error.
*/
TCPsocket SDLNet_TCP_Accept(TCPsocket server)
{
TCPsocket sock;
struct sockaddr_in sock_addr;
int sock_alen;
/* Only server sockets can accept */
if ( ! server->sflag ) {
SDLNet_SetError("Only server sockets can accept()");
return(NULL);
}
server->ready = 0;
/* Allocate a TCP socket structure */
sock = (TCPsocket)malloc(sizeof(*sock));
if ( sock == NULL ) {
SDLNet_SetError("Out of memory");
goto error_return;
}
/* Accept a new TCP connection on a server socket */
sock_alen = sizeof(sock_addr);
sock->channel = accept(server->channel, (struct sockaddr *)&sock_addr,
#ifdef USE_GUSI_SOCKETS
(unsigned int *)&sock_alen);
#else
&sock_alen);
#endif
if ( sock->channel == SOCKET_ERROR ) {
SDLNet_SetError("accept() failed");
goto error_return;
}
#ifdef WIN32
{
/* passing a zero value, socket mode set to block on */
unsigned long mode = 0;
ioctlsocket (sock->channel, FIONBIO, &mode);
}
#elif defined(O_NONBLOCK)
{
int flags = fcntl(sock->channel, F_GETFL, 0);
fcntl(sock->channel, F_SETFL, flags & ~O_NONBLOCK);
}
#endif /* WIN32 */
sock->remoteAddress.host = sock_addr.sin_addr.s_addr;
sock->remoteAddress.port = sock_addr.sin_port;
sock->sflag = 0;
sock->ready = 0;
/* The socket is ready */
return(sock);
error_return:
SDLNet_TCP_Close(sock);
return(NULL);
}
/* Get the IP address of the remote system associated with the socket.
If the socket is a server socket, this function returns NULL.
*/
IPaddress *SDLNet_TCP_GetPeerAddress(TCPsocket sock)
{
if ( sock->sflag ) {
return(NULL);
}
return(&sock->remoteAddress);
}
/* Send 'len' bytes of 'data' over the non-server socket 'sock'
This function returns the actual amount of data sent. If the return value
is less than the amount of data sent, then either the remote connection was
closed, or an unknown socket error occurred.
*/
int SDLNet_TCP_Send(TCPsocket sock, const void *datap, int len)
{
const Uint8 *data = (const Uint8 *)datap; /* For pointer arithmetic */
int sent, left;
/* Server sockets are for accepting connections only */
if ( sock->sflag ) {
SDLNet_SetError("Server sockets cannot send");
return(-1);
}
/* Keep sending data until it's sent or an error occurs */
left = len;
sent = 0;
errno = 0;
do {
len = send(sock->channel, (const char *) data, left, 0);
if ( len > 0 ) {
sent += len;
left -= len;
data += len;
}
} while ( (left > 0) && ((len > 0) || (errno == EINTR)) );
return(sent);
}
/* Receive up to 'maxlen' bytes of data over the non-server socket 'sock',
and store them in the buffer pointed to by 'data'.
This function returns the actual amount of data received. If the return
value is less than or equal to zero, then either the remote connection was
closed, or an unknown socket error occurred.
*/
int SDLNet_TCP_Recv(TCPsocket sock, void *data, int maxlen)
{
int len;
/* Server sockets are for accepting connections only */
if ( sock->sflag ) {
SDLNet_SetError("Server sockets cannot receive");
return(-1);
}
errno = 0;
do {
len = recv(sock->channel, (char *) data, maxlen, 0);
} while ( errno == EINTR );
sock->ready = 0;
return(len);
}
/* Close a TCP network socket */
void SDLNet_TCP_Close(TCPsocket sock)
{
if ( sock != NULL ) {
if ( sock->channel != INVALID_SOCKET ) {
closesocket(sock->channel);
}
free(sock);
}
}
#endif /* MACOS_OPENTRANSPORT */

815
SDL_net/src/SDLnetUDP.c Normal file
View file

@ -0,0 +1,815 @@
/*
SDL_net: An example cross-platform network library for use with SDL
Copyright (C) 1997-2009 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/* $Id: SDLnetUDP.c 4211 2008-12-08 00:27:32Z slouken $ */
#include "SDLnetsys.h"
#include "SDL_net.h"
#ifdef MACOS_OPENTRANSPORT
#include <Events.h>
#endif
struct _UDPsocket {
int ready;
SOCKET channel;
IPaddress address;
#ifdef MACOS_OPENTRANSPORT
OTEventCode newEvent;
OTEventCode event;
OTEventCode curEvent;
OTEventCode newCompletion;
OTEventCode completion;
OTEventCode curCompletion;
TEndpointInfo info;
Boolean readShutdown;
Boolean writeShutdown;
OSStatus error;
OTConfigurationRef config; // Master configuration. you can clone this.
#endif /* MACOS_OPENTRANSPORT */
struct UDP_channel {
int numbound;
IPaddress address[SDLNET_MAX_UDPADDRESSES];
} binding[SDLNET_MAX_UDPCHANNELS];
};
#ifdef MACOS_OPENTRANSPORT
/* A helper function for Mac OpenTransport support*/
// This function is a complete copy from GUSI
// ( masahiro minami<elsur@aaa.letter.co.jp> )
// ( 01/02/19 )
//
// I guess this function should be put in SDLnet.c
// ( 010315 masahiro minami<elsur@aaa.letter.co.jp>)
// (TODO)
static __inline__ Uint32 CompleteMask(OTEventCode code)
{
return 1 << (code & 0x1F);
}
/* Notifier for async OT calls */
// This function is completely same as AsyncTCPNotifier,
// except for the argument, UDPsocket / TCPsocket
// ( 010315 masahiro minami<elsur@aaa.letter.co.jp>)
static pascal void AsyncUDPNotifier( UDPsocket sock, OTEventCode code,
OTResult result, void* cookie )
{
switch( code & 0x7f000000L)
{
case 0:
sock->newEvent |= code;
result = 0;
break;
case kCOMPLETEEVENT:
if(!(code & 0x00FFFFE0 ))
sock->newCompletion |= CompleteMask( code );
if( code == T_OPENCOMPLETE )
sock->channel = (SOCKET)(cookie);
break;
default:
if( code != kOTProviderWillClose )
result = 0;
}
// Do we need these ???? TODO
// sock->SetAsyncMacError( result );
// sock->Wakeup();
// Do we need to ?
//YieldToAnyThread();
}
/* Retrieve OT event */
// This function is completely same as AsyncTCPPopEvent,
// except for the argument, UDPsocket / TCPsocket
// ( 010315 masahiro minami<elsur@aaa.letter.co.jp>)
static void AsyncUDPPopEvent( UDPsocket sock )
{
// Make sure OT calls are not interrupted
// Not sure if we really need this.
OTEnterNotifier( sock->channel );
sock->event |= (sock->curEvent = sock->newEvent );
sock->completion |= ( sock->curCompletion = sock->newCompletion );
sock->newEvent = sock->newCompletion = 0;
OTLeaveNotifier( sock->channel );
if( sock->curEvent & T_UDERR)
{
// We just clear the error.
// Should we feed this back to users ?
// (TODO )
OTRcvUDErr( sock->channel, NULL );
}
// Remote is disconnecting...
if( sock->curEvent & ( T_DISCONNECT | T_ORDREL ))
{
sock->readShutdown = true;
}
if( sock->curEvent &T_CONNECT)
{
// Ignore the info of remote (second parameter).
// Shoule we care ?
// (TODO)
OTRcvConnect( sock->channel, NULL );
}
if( sock->curEvent & T_ORDREL )
{
OTRcvOrderlyDisconnect( sock->channel );
}
if( sock->curEvent & T_DISCONNECT )
{
OTRcvDisconnect( sock->channel, NULL );
}
// Should we ??
// (010318 masahiro minami<elsur@aaa.letter.co.jp>
//YieldToAnyThread();
}
/* Create a new UDPsocket */
// Because TCPsocket structure gets bigger and bigger,
// I think we'd better have a constructor function and delete function.
// ( 01/02/25 masahiro minami<elsur@aaa.letter.co.jp> )
/*static*/ UDPsocket AsyncUDPNewSocket()
{
UDPsocket sock;
sock = (UDPsocket)malloc(sizeof(*sock));
if ( sock == NULL ) {
SDLNet_SetError("Out of memory");
return NULL;
}
sock->newEvent = 0;
sock->event = 0;
sock->curEvent = 0;
sock->newCompletion = 0;
sock->completion = 0;
sock->curCompletion = 0;
//sock->info = NULL;
sock->readShutdown = sock->writeShutdown = false;
sock->error = 0;
sock->config = NULL;
return sock;
}
#endif /* MACOS_OPENTRANSPORT */
/* Allocate/free a single UDP packet 'size' bytes long.
The new packet is returned, or NULL if the function ran out of memory.
*/
extern UDPpacket *SDLNet_AllocPacket(int size)
{
UDPpacket *packet;
int error;
error = 1;
packet = (UDPpacket *)malloc(sizeof(*packet));
if ( packet != NULL ) {
packet->maxlen = size;
packet->data = (Uint8 *)malloc(size);
if ( packet->data != NULL ) {
error = 0;
}
}
if ( error ) {
SDLNet_FreePacket(packet);
packet = NULL;
}
return(packet);
}
int SDLNet_ResizePacket(UDPpacket *packet, int newsize)
{
Uint8 *newdata;
newdata = (Uint8 *)malloc(newsize);
if ( newdata != NULL ) {
free(packet->data);
packet->data = newdata;
packet->maxlen = newsize;
}
return(packet->maxlen);
}
extern void SDLNet_FreePacket(UDPpacket *packet)
{
if ( packet ) {
if ( packet->data )
free(packet->data);
free(packet);
}
}
/* Allocate/Free a UDP packet vector (array of packets) of 'howmany' packets,
each 'size' bytes long.
A pointer to the packet array is returned, or NULL if the function ran out
of memory.
*/
UDPpacket **SDLNet_AllocPacketV(int howmany, int size)
{
UDPpacket **packetV;
packetV = (UDPpacket **)malloc((howmany+1)*sizeof(*packetV));
if ( packetV != NULL ) {
int i;
for ( i=0; i<howmany; ++i ) {
packetV[i] = SDLNet_AllocPacket(size);
if ( packetV[i] == NULL ) {
break;
}
}
packetV[i] = NULL;
if ( i != howmany ) {
SDLNet_FreePacketV(packetV);
packetV = NULL;
}
}
return(packetV);
}
void SDLNet_FreePacketV(UDPpacket **packetV)
{
if ( packetV ) {
int i;
for ( i=0; packetV[i]; ++i ) {
SDLNet_FreePacket(packetV[i]);
}
free(packetV);
}
}
/* Since the UNIX/Win32/BeOS code is so different from MacOS,
we'll just have two completely different sections here.
*/
/* Open a UDP network socket
If 'port' is non-zero, the UDP socket is bound to a fixed local port.
*/
extern UDPsocket SDLNet_UDP_Open(Uint16 port)
{
UDPsocket sock;
#ifdef MACOS_OPENTRANSPORT
EndpointRef dummy = NULL;
#endif
/* Allocate a UDP socket structure */
sock = (UDPsocket)malloc(sizeof(*sock));
if ( sock == NULL ) {
SDLNet_SetError("Out of memory");
goto error_return;
}
memset(sock, 0, sizeof(*sock));
/* Open the socket */
#ifdef MACOS_OPENTRANSPORT
{
sock->error = OTAsyncOpenEndpoint(
OTCreateConfiguration(kUDPName),0, &(sock->info),
(OTNotifyProcPtr)AsyncUDPNotifier, sock );
AsyncUDPPopEvent( sock );
while( !sock->error && !( sock->completion & CompleteMask(T_OPENCOMPLETE)))
{
AsyncUDPPopEvent( sock );
}
if( sock->error )
{
SDLNet_SetError("Could not open UDP socket");
goto error_return;
}
// Should we ??
// (01/05/03 minami<elsur@aaa.letter.co.jp>
OTSetBlocking( sock->channel );
}
#else
sock->channel = socket(AF_INET, SOCK_DGRAM, 0);
#endif /* MACOS_OPENTRANSPORT */
if ( sock->channel == INVALID_SOCKET )
{
SDLNet_SetError("Couldn't create socket");
goto error_return;
}
#ifdef MACOS_OPENTRANSPORT
{
InetAddress required, assigned;
TBind req_addr, assigned_addr;
OSStatus status;
InetInterfaceInfo info;
memset(&assigned_addr, 0, sizeof(assigned_addr));
assigned_addr.addr.maxlen = sizeof(assigned);
assigned_addr.addr.len = sizeof(assigned);
assigned_addr.addr.buf = (UInt8 *) &assigned;
if ( port ) {
status = OTInetGetInterfaceInfo( &info, kDefaultInetInterface );
if( status != kOTNoError )
goto error_return;
OTInitInetAddress(&required, port, info.fAddress );
req_addr.addr.maxlen = sizeof( required );
req_addr.addr.len = sizeof( required );
req_addr.addr.buf = (UInt8 *) &required;
sock->error = OTBind(sock->channel, &req_addr, &assigned_addr);
} else {
sock->error = OTBind(sock->channel, nil, &assigned_addr );
}
AsyncUDPPopEvent(sock);
while( !sock->error && !(sock->completion & CompleteMask(T_BINDCOMPLETE)))
{
AsyncUDPPopEvent(sock);
}
if (sock->error != noErr)
{
SDLNet_SetError("Couldn't bind to local port, OTBind() = %d",(int) status);
goto error_return;
}
sock->address.host = assigned.fHost;
sock->address.port = assigned.fPort;
#ifdef DEBUG_NET
printf("UDP open host = %d, port = %d\n", assigned.fHost, assigned.fPort );
#endif
}
#else
/* Bind locally, if appropriate */
if ( port )
{
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
sock_addr.sin_addr.s_addr = INADDR_ANY;
sock_addr.sin_port = SDL_SwapBE16(port);
/* Bind the socket for listening */
if ( bind(sock->channel, (struct sockaddr *)&sock_addr,
sizeof(sock_addr)) == SOCKET_ERROR ) {
SDLNet_SetError("Couldn't bind to local port");
goto error_return;
}
/* Fill in the channel host address */
sock->address.host = sock_addr.sin_addr.s_addr;
sock->address.port = sock_addr.sin_port;
}
#ifdef SO_BROADCAST
/* Allow LAN broadcasts with the socket */
{ int yes = 1;
setsockopt(sock->channel, SOL_SOCKET, SO_BROADCAST, (char*)&yes, sizeof(yes));
}
#endif
#ifdef IP_ADD_MEMBERSHIP
/* Receive LAN multicast packets on 224.0.0.1
This automatically works on Mac OS X, Linux and BSD, but needs
this code on Windows.
*/
/* A good description of multicast can be found here:
http://www.docs.hp.com/en/B2355-90136/ch05s05.html
*/
/* FIXME: Add support for joining arbitrary groups to the API */
{
struct ip_mreq g;
g.imr_multiaddr.s_addr = inet_addr("224.0.0.1");
g.imr_interface.s_addr = INADDR_ANY;
setsockopt(sock->channel, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(char*)&g, sizeof(g));
}
#endif
#endif /* MACOS_OPENTRANSPORT */
/* The socket is ready */
return(sock);
error_return:
#ifdef MACOS_OPENTRANSPORT
if( dummy )
OTCloseProvider( dummy );
#endif
SDLNet_UDP_Close(sock);
return(NULL);
}
/* Verify that the channel is in the valid range */
static int ValidChannel(int channel)
{
if ( (channel < 0) || (channel >= SDLNET_MAX_UDPCHANNELS) ) {
SDLNet_SetError("Invalid channel");
return(0);
}
return(1);
}
/* Bind the address 'address' to the requested channel on the UDP socket.
If the channel is -1, then the first unbound channel will be bound with
the given address as it's primary address.
If the channel is already bound, this new address will be added to the
list of valid source addresses for packets arriving on the channel.
If the channel is not already bound, then the address becomes the primary
address, to which all outbound packets on the channel are sent.
This function returns the channel which was bound, or -1 on error.
*/
int SDLNet_UDP_Bind(UDPsocket sock, int channel, IPaddress *address)
{
struct UDP_channel *binding;
if ( channel == -1 ) {
for ( channel=0; channel < SDLNET_MAX_UDPCHANNELS; ++channel ) {
binding = &sock->binding[channel];
if ( binding->numbound < SDLNET_MAX_UDPADDRESSES ) {
break;
}
}
} else {
if ( ! ValidChannel(channel) ) {
return(-1);
}
binding = &sock->binding[channel];
}
if ( binding->numbound == SDLNET_MAX_UDPADDRESSES ) {
SDLNet_SetError("No room for new addresses");
return(-1);
}
binding->address[binding->numbound++] = *address;
return(channel);
}
/* Unbind all addresses from the given channel */
void SDLNet_UDP_Unbind(UDPsocket sock, int channel)
{
if ( (channel >= 0) && (channel < SDLNET_MAX_UDPCHANNELS) ) {
sock->binding[channel].numbound = 0;
}
}
/* Get the primary IP address of the remote system associated with the
socket and channel.
If the channel is not bound, this function returns NULL.
*/
IPaddress *SDLNet_UDP_GetPeerAddress(UDPsocket sock, int channel)
{
IPaddress *address;
address = NULL;
switch (channel) {
case -1:
/* Return the actual address of the socket */
address = &sock->address;
break;
default:
/* Return the address of the bound channel */
if ( ValidChannel(channel) &&
(sock->binding[channel].numbound > 0) ) {
address = &sock->binding[channel].address[0];
}
break;
}
return(address);
}
/* Send a vector of packets to the the channels specified within the packet.
If the channel specified in the packet is -1, the packet will be sent to
the address in the 'src' member of the packet.
Each packet will be updated with the status of the packet after it has
been sent, -1 if the packet send failed.
This function returns the number of packets sent.
*/
int SDLNet_UDP_SendV(UDPsocket sock, UDPpacket **packets, int npackets)
{
int numsent, i, j;
struct UDP_channel *binding;
int status;
#ifndef MACOS_OPENTRANSPORT
int sock_len;
struct sockaddr_in sock_addr;
/* Set up the variables to send packets */
sock_len = sizeof(sock_addr);
#endif
numsent = 0;
for ( i=0; i<npackets; ++i )
{
/* if channel is < 0, then use channel specified in sock */
if ( packets[i]->channel < 0 )
{
#ifdef MACOS_OPENTRANSPORT
TUnitData OTpacket;
InetAddress address;
memset(&OTpacket, 0, sizeof(OTpacket));
OTpacket.addr.buf = (Uint8 *)&address;
OTpacket.addr.len = (sizeof address);
OTpacket.udata.buf = packets[i]->data;
OTpacket.udata.len = packets[i]->len;
OTInitInetAddress(&address, packets[i]->address.port, packets[i]->address.host);
#ifdef DEBUG_NET
printf("Packet send address: 0x%8.8x:%d, length = %d\n", packets[i]->address.host, packets[i]->address.port, packets[i]->len);
#endif
status = OTSndUData(sock->channel, &OTpacket);
#ifdef DEBUG_NET
printf("SDLNet_UDP_SendV OTSndUData return value is ;%d\n", status );
#endif
AsyncUDPPopEvent( sock );
packets[i]->status = status;
if (status == noErr)
{
++numsent;
}
#else
sock_addr.sin_addr.s_addr = packets[i]->address.host;
sock_addr.sin_port = packets[i]->address.port;
sock_addr.sin_family = AF_INET;
status = sendto(sock->channel,
packets[i]->data, packets[i]->len, 0,
(struct sockaddr *)&sock_addr,sock_len);
if ( status >= 0 )
{
packets[i]->status = status;
++numsent;
}
#endif /* MACOS_OPENTRANSPORT */
}
else
{
/* Send to each of the bound addresses on the channel */
#ifdef DEBUG_NET
printf("SDLNet_UDP_SendV sending packet to channel = %d\n", packets[i]->channel );
#endif
binding = &sock->binding[packets[i]->channel];
for ( j=binding->numbound-1; j>=0; --j )
{
#ifdef MACOS_OPENTRANSPORT
TUnitData OTpacket;
InetAddress address;
OTInitInetAddress(&address, binding->address[j].port,binding->address[j].host);
#ifdef DEBUG_NET
printf("Packet send address: 0x%8.8x:%d, length = %d\n", binding->address[j].host, binding->address[j].port, packets[i]->len);
#endif
memset(&OTpacket, 0, sizeof(OTpacket));
OTpacket.addr.buf = (Uint8 *)&address;
OTpacket.addr.len = (sizeof address);
OTpacket.udata.buf = packets[i]->data;
OTpacket.udata.len = packets[i]->len;
status = OTSndUData(sock->channel, &OTpacket);
#ifdef DEBUG_NET
printf("SDLNet_UDP_SendV OTSndUData returne value is;%d\n", status );
#endif
AsyncUDPPopEvent(sock);
packets[i]->status = status;
if (status == noErr)
{
++numsent;
}
#else
sock_addr.sin_addr.s_addr = binding->address[j].host;
sock_addr.sin_port = binding->address[j].port;
sock_addr.sin_family = AF_INET;
status = sendto(sock->channel,
packets[i]->data, packets[i]->len, 0,
(struct sockaddr *)&sock_addr,sock_len);
if ( status >= 0 )
{
packets[i]->status = status;
++numsent;
}
#endif /* MACOS_OPENTRANSPORT */
}
}
}
return(numsent);
}
int SDLNet_UDP_Send(UDPsocket sock, int channel, UDPpacket *packet)
{
/* This is silly, but... */
packet->channel = channel;
return(SDLNet_UDP_SendV(sock, &packet, 1));
}
/* Returns true if a socket is has data available for reading right now */
static int SocketReady(SOCKET sock)
{
int retval = 0;
#ifdef MACOS_OPENTRANSPORT
OTResult status;
#else
struct timeval tv;
fd_set mask;
#endif
#ifdef MACOS_OPENTRANSPORT
//status = OTGetEndpointState(sock);
status = OTLook(sock);
if( status > 0 )
retval = 1;
/* switch( status )
{
// case T_IDLE:
case T_DATAXFER:
// case T_INREL:
retval = 1;
break;
default:
OTCountDataBytes( sock, &numBytes );
if( numBytes )
retval = 1;
}*/
#else
/* Check the file descriptors for available data */
do {
errno = 0;
/* Set up the mask of file descriptors */
FD_ZERO(&mask);
FD_SET(sock, &mask);
/* Set up the timeout */
tv.tv_sec = 0;
tv.tv_usec = 0;
/* Look! */
retval = select(sock+1, &mask, NULL, NULL, &tv);
} while ( errno == EINTR );
#endif /* MACOS_OPENTRANSPORT */
return(retval == 1);
}
/* Receive a vector of pending packets from the UDP socket.
The returned packets contain the source address and the channel they arrived
on. If they did not arrive on a bound channel, the the channel will be set
to -1.
This function returns the number of packets read from the network, or -1
on error. This function does not block, so can return 0 packets pending.
*/
extern int SDLNet_UDP_RecvV(UDPsocket sock, UDPpacket **packets)
{
int numrecv, i, j;
struct UDP_channel *binding;
#ifdef MACOS_OPENTRANSPORT
TUnitData OTpacket;
OTFlags flags;
InetAddress address;
#else
int sock_len;
struct sockaddr_in sock_addr;
#endif
numrecv = 0;
while ( packets[numrecv] && SocketReady(sock->channel) )
{
UDPpacket *packet;
packet = packets[numrecv];
#ifdef MACOS_OPENTRANSPORT
memset(&OTpacket, 0, sizeof(OTpacket));
OTpacket.addr.buf = (Uint8 *)&address;
OTpacket.addr.maxlen = (sizeof address);
OTpacket.udata.buf = packet->data;
OTpacket.udata.maxlen = packet->maxlen;
packet->status = OTRcvUData(sock->channel, &OTpacket, &flags);
#ifdef DEBUG_NET
printf("Packet status: %d\n", packet->status);
#endif
AsyncUDPPopEvent(sock);
if (packet->status == noErr)
{
packet->len = OTpacket.udata.len;
packet->address.host = address.fHost;
packet->address.port = address.fPort;
#ifdef DEBUG_NET
printf("Packet address: 0x%8.8x:%d, length = %d\n", packet->address.host, packet->address.port, packet->len);
#endif
}
#else
sock_len = sizeof(sock_addr);
packet->status = recvfrom(sock->channel,
packet->data, packet->maxlen, 0,
(struct sockaddr *)&sock_addr,
#ifdef USE_GUSI_SOCKETS
(unsigned int *)&sock_len);
#else
&sock_len);
#endif
if ( packet->status >= 0 ) {
packet->len = packet->status;
packet->address.host = sock_addr.sin_addr.s_addr;
packet->address.port = sock_addr.sin_port;
}
#endif
if (packet->status >= 0)
{
packet->channel = -1;
for (i=(SDLNET_MAX_UDPCHANNELS-1); i>=0; --i )
{
binding = &sock->binding[i];
for ( j=binding->numbound-1; j>=0; --j )
{
if ( (packet->address.host == binding->address[j].host) &&
(packet->address.port == binding->address[j].port) )
{
packet->channel = i;
goto foundit; /* break twice */
}
}
}
foundit:
++numrecv;
}
else
{
packet->len = 0;
}
}
sock->ready = 0;
return(numrecv);
}
/* Receive a single packet from the UDP socket.
The returned packet contains the source address and the channel it arrived
on. If it did not arrive on a bound channel, the the channel will be set
to -1.
This function returns the number of packets read from the network, or -1
on error. This function does not block, so can return 0 packets pending.
*/
int SDLNet_UDP_Recv(UDPsocket sock, UDPpacket *packet)
{
UDPpacket *packets[2];
/* Receive a packet array of 1 */
packets[0] = packet;
packets[1] = NULL;
return(SDLNet_UDP_RecvV(sock, packets));
}
/* Close a UDP network socket */
extern void SDLNet_UDP_Close(UDPsocket sock)
{
if ( sock != NULL )
{
if ( sock->channel != INVALID_SOCKET )
{
#ifdef MACOS_OPENTRANSPORT
OTUnbind(sock->channel);
OTCloseProvider(sock->channel);
#else
closesocket(sock->channel);
#endif /* MACOS_OPENTRANSPORT */
}
free(sock);
}
}

226
SDL_net/src/SDLnetselect.c Normal file
View file

@ -0,0 +1,226 @@
/*
SDL_net: An example cross-platform network library for use with SDL
Copyright (C) 1997-2009 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/* $Id: SDLnetselect.c 4211 2008-12-08 00:27:32Z slouken $ */
#include "SDLnetsys.h"
#include "SDL_net.h"
/* The select() API for network sockets */
struct SDLNet_Socket {
int ready;
SOCKET channel;
#ifdef MACOS_OPENTRANSPORT
OTEventCode curEvent;
#endif
};
struct _SDLNet_SocketSet {
int numsockets;
int maxsockets;
struct SDLNet_Socket **sockets;
};
/* Allocate a socket set for use with SDLNet_CheckSockets()
This returns a socket set for up to 'maxsockets' sockets, or NULL if
the function ran out of memory.
*/
SDLNet_SocketSet SDLNet_AllocSocketSet(int maxsockets)
{
struct _SDLNet_SocketSet *set;
int i;
set = (struct _SDLNet_SocketSet *)malloc(sizeof(*set));
if ( set != NULL ) {
set->numsockets = 0;
set->maxsockets = maxsockets;
set->sockets = (struct SDLNet_Socket **)malloc
(maxsockets*sizeof(*set->sockets));
if ( set->sockets != NULL ) {
for ( i=0; i<maxsockets; ++i ) {
set->sockets[i] = NULL;
}
} else {
free(set);
set = NULL;
}
}
return(set);
}
/* Add a socket to a set of sockets to be checked for available data */
int SDLNet_AddSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock)
{
if ( sock != NULL ) {
if ( set->numsockets == set->maxsockets ) {
SDLNet_SetError("socketset is full");
return(-1);
}
set->sockets[set->numsockets++] = (struct SDLNet_Socket *)sock;
}
return(set->numsockets);
}
/* Remove a socket from a set of sockets to be checked for available data */
int SDLNet_DelSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock)
{
int i;
if ( sock != NULL ) {
for ( i=0; i<set->numsockets; ++i ) {
if ( set->sockets[i] == (struct SDLNet_Socket *)sock ) {
break;
}
}
if ( i == set->numsockets ) {
SDLNet_SetError("socket not found in socketset");
return(-1);
}
--set->numsockets;
for ( ; i<set->numsockets; ++i ) {
set->sockets[i] = set->sockets[i+1];
}
}
return(set->numsockets);
}
/* This function checks to see if data is available for reading on the
given set of sockets. If 'timeout' is 0, it performs a quick poll,
otherwise the function returns when either data is available for
reading, or the timeout in milliseconds has elapsed, which ever occurs
first. This function returns the number of sockets ready for reading,
or -1 if there was an error with the select() system call.
*/
#ifdef MACOS_OPENTRANSPORT
int SDLNet_CheckSockets(SDLNet_SocketSet set, Uint32 timeout)
{
Uint32 stop;
int numReady;
/* Loop, polling the network devices */
stop = SDL_GetTicks() + timeout;
do
{
OTResult status;
size_t numBytes;
int i;
numReady = 0;
for (i = set->numsockets-1;i >= 0;--i)
{
status = OTLook( set->sockets[i]->channel );
if( status > 0 )
{
switch( status )
{
case T_UDERR:
OTRcvUDErr( set->sockets[i]->channel , nil);
break;
case T_DISCONNECT:
OTRcvDisconnect( set->sockets[i]->channel, nil );
break;
case T_ORDREL:
OTRcvOrderlyDisconnect(set->sockets[i]->channel );
break;
case T_CONNECT:
OTRcvConnect( set->sockets[i]->channel, nil );
break;
default:
set->sockets[i]->ready = 1;
++numReady;
}
}
else if( OTCountDataBytes(set->sockets[i]->channel, &numBytes ) != kOTNoDataErr )
{
set->sockets[i]->ready = 1;
++numReady;
}
else
set->sockets[i]->ready = 0;
}
} while (!numReady && (SDL_GetTicks() < stop));
return(numReady);
}
#else
int SDLNet_CheckSockets(SDLNet_SocketSet set, Uint32 timeout)
{
int i;
SOCKET maxfd;
int retval;
struct timeval tv;
fd_set mask;
/* Find the largest file descriptor */
maxfd = 0;
for ( i=set->numsockets-1; i>=0; --i ) {
if ( set->sockets[i]->channel > maxfd ) {
maxfd = set->sockets[i]->channel;
}
}
/* Check the file descriptors for available data */
do {
errno = 0;
/* Set up the mask of file descriptors */
FD_ZERO(&mask);
for ( i=set->numsockets-1; i>=0; --i ) {
FD_SET(set->sockets[i]->channel, &mask);
}
/* Set up the timeout */
tv.tv_sec = timeout/1000;
tv.tv_usec = (timeout%1000)*1000;
/* Look! */
retval = select(maxfd+1, &mask, NULL, NULL, &tv);
} while ( errno == EINTR );
/* Mark all file descriptors ready that have data available */
if ( retval > 0 ) {
for ( i=set->numsockets-1; i>=0; --i ) {
if ( FD_ISSET(set->sockets[i]->channel, &mask) ) {
set->sockets[i]->ready = 1;
}
}
}
return(retval);
}
#endif /* MACOS_OPENTRANSPORT */
/* Free a set of sockets allocated by SDL_NetAllocSocketSet() */
extern void SDLNet_FreeSocketSet(SDLNet_SocketSet set)
{
if ( set ) {
free(set->sockets);
free(set);
}
}

84
SDL_net/src/SDLnetsys.h Normal file
View file

@ -0,0 +1,84 @@
/*
SDL_net: An example cross-platform network library for use with SDL
Copyright (C) 1997-2009 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/* $Id: SDLnetsys.h 4211 2008-12-08 00:27:32Z slouken $ */
/* Include normal system headers */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifdef macintosh
#ifndef USE_GUSI_SOCKETS
#define MACOS_OPENTRANSPORT
//#error Open Transport driver is broken
#endif
#endif /* macintosh */
/* Include system network headers */
#ifdef MACOS_OPENTRANSPORT
#include <OpenTransport.h>
#include <OpenTptInternet.h>
#else
#if defined(__WIN32__) || defined(WIN32)
#define __USE_W32_SOCKETS
#include <winsock.h>
#else /* UNIX */
#ifdef __OS2__
#include <types.h>
#include <sys/ioctl.h>
#endif
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#ifndef __BEOS__
#include <arpa/inet.h>
#endif
#ifdef linux /* FIXME: what other platforms have this? */
#include <netinet/tcp.h>
#endif
#include <netdb.h>
#include <sys/socket.h>
#endif /* WIN32 */
#endif /* Open Transport */
/* System-dependent definitions */
#ifdef MACOS_OPENTRANSPORT
//#define closesocket OTCloseProvider
#define closesocket OTSndOrderlyDisconnect
#define SOCKET EndpointRef
#define INVALID_SOCKET kOTInvalidEndpointRef
#else
#ifndef __USE_W32_SOCKETS
#ifdef __OS2__
#define closesocket soclose
#else /* !__OS2__ */
#define closesocket close
#endif /* __OS2__ */
#define SOCKET int
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#endif /* __USE_W32_SOCKETS */
#endif /* Open Transport */

8
SDL_net/src/autogen.sh Normal file
View file

@ -0,0 +1,8 @@
#!/bin/sh
#
aclocal -I acinclude
automake --foreign --include-deps --add-missing --copy
autoconf
#./configure $*
echo "Now you are ready to run ./configure"

483
SDL_net/src/chat.cpp Normal file
View file

@ -0,0 +1,483 @@
/*
CHAT: A chat client using the SDL example network and GUI libraries
Copyright (C) 1997-2009 Sam Lantinga
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
5635-34 Springhouse Dr.
Pleasanton, CA 94588 (USA)
slouken@devolution.com
*/
/* Note that this isn't necessarily the way to run a chat system.
This is designed to excercise the network code more than be really
functional.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDL_net.h"
#ifdef macintosh
#include "GUI.h"
#include "GUI_widgets.h"
#else
#include <GUI/GUI.h>
#include <GUI/GUI_widgets.h>
#endif
#include "chat.h"
/* Global variables */
static TCPsocket tcpsock = NULL;
static UDPsocket udpsock = NULL;
static SDLNet_SocketSet socketset = NULL;
static UDPpacket **packets = NULL;
static struct {
int active;
Uint8 name[256+1];
} people[CHAT_MAXPEOPLE];
static GUI *gui = NULL;
static GUI_TermWin *termwin;
static GUI_TermWin *sendwin;
enum image_names {
IMAGE_QUIT,
IMAGE_SCROLL_UP,
IMAGE_SCROLL_DN,
NUM_IMAGES
};
char *image_files[NUM_IMAGES] = {
"quit.bmp", "scroll_up.bmp", "scroll_dn.bmp"
};
SDL_Surface *images[NUM_IMAGES];
void SendHello(char *name)
{
IPaddress *myip;
char hello[1+1+256];
int i, n;
/* No people are active at first */
for ( i=0; i<CHAT_MAXPEOPLE; ++i ) {
people[i].active = 0;
}
if ( tcpsock != NULL ) {
/* Get our chat handle */
if ( (name == NULL) &&
((name=getenv("CHAT_USER")) == NULL) &&
((name=getenv("USER")) == NULL ) ) {
name="Unknown";
}
termwin->AddText("Using name '%s'\n", name);
/* Construct the packet */
hello[0] = CHAT_HELLO;
myip = SDLNet_UDP_GetPeerAddress(udpsock, -1);
memcpy(&hello[CHAT_HELLO_PORT], &myip->port, 2);
if ( strlen(name) > 255 ) {
n = 255;
} else {
n = strlen(name);
}
hello[CHAT_HELLO_NLEN] = n;
strncpy(&hello[CHAT_HELLO_NAME], name, n);
hello[CHAT_HELLO_NAME+n++] = 0;
/* Send it to the server */
SDLNet_TCP_Send(tcpsock, hello, CHAT_HELLO_NAME+n);
}
}
void SendBuf(char *buf, int len)
{
int i;
/* Redraw the prompt and add a newline to the buffer */
sendwin->Clear();
sendwin->AddText(CHAT_PROMPT);
buf[len++] = '\n';
/* Send the text to each of our active channels */
for ( i=0; i < CHAT_MAXPEOPLE; ++i ) {
if ( people[i].active ) {
if ( len > packets[0]->maxlen ) {
len = packets[0]->maxlen;
}
memcpy(packets[0]->data, buf, len);
packets[0]->len = len;
SDLNet_UDP_Send(udpsock, i, packets[0]);
}
}
}
void SendKey(SDLKey key, Uint16 unicode)
{
static char keybuf[80-sizeof(CHAT_PROMPT)+1];
static int keypos = 0;
unsigned char ch;
/* We don't handle wide UNICODE characters yet */
if ( unicode > 255 ) {
return;
}
ch = (unsigned char)unicode;
/* Add the key to the buffer, and send it if we have a line */
switch (ch) {
case '\0':
break;
case '\r':
case '\n':
/* Send our line of text */
SendBuf(keybuf, keypos);
keypos = 0;
break;
case '\b':
/* If there's data, back up over it */
if ( keypos > 0 ) {
sendwin->AddText((char *)&ch, 1);
--keypos;
}
break;
default:
/* If the buffer is full, send it */
if ( keypos == (sizeof(keybuf)/sizeof(keybuf[0]))-1 ) {
SendBuf(keybuf, keypos);
keypos = 0;
}
/* Add the text to our send buffer */
sendwin->AddText((char *)&ch, 1);
keybuf[keypos++] = ch;
break;
}
}
int HandleServerData(Uint8 *data)
{
int used;
switch (data[0]) {
case CHAT_ADD: {
Uint8 which;
IPaddress newip;
/* Figure out which channel we got */
which = data[CHAT_ADD_SLOT];
if ((which >= CHAT_MAXPEOPLE) || people[which].active) {
/* Invalid channel?? */
break;
}
/* Get the client IP address */
newip.host=SDLNet_Read32(&data[CHAT_ADD_HOST]);
newip.port=SDLNet_Read16(&data[CHAT_ADD_PORT]);
/* Copy name into channel */
memcpy(people[which].name, &data[CHAT_ADD_NAME], 256);
people[which].name[256] = 0;
people[which].active = 1;
/* Let the user know what happened */
termwin->AddText(
"* New client on %d from %d.%d.%d.%d:%d (%s)\n", which,
(newip.host>>24)&0xFF, (newip.host>>16)&0xFF,
(newip.host>>8)&0xFF, newip.host&0xFF,
newip.port, people[which].name);
/* Put the address back in network form */
newip.host = SDL_SwapBE32(newip.host);
newip.port = SDL_SwapBE16(newip.port);
/* Bind the address to the UDP socket */
SDLNet_UDP_Bind(udpsock, which, &newip);
}
used = CHAT_ADD_NAME+data[CHAT_ADD_NLEN];
break;
case CHAT_DEL: {
Uint8 which;
/* Figure out which channel we lost */
which = data[CHAT_DEL_SLOT];
if ( (which >= CHAT_MAXPEOPLE) ||
! people[which].active ) {
/* Invalid channel?? */
break;
}
people[which].active = 0;
/* Let the user know what happened */
termwin->AddText(
"* Lost client on %d (%s)\n", which, people[which].name);
/* Unbind the address on the UDP socket */
SDLNet_UDP_Unbind(udpsock, which);
}
used = CHAT_DEL_LEN;
break;
case CHAT_BYE: {
termwin->AddText("* Chat server full\n");
}
used = CHAT_BYE_LEN;
break;
default: {
/* Unknown packet type?? */;
}
used = 0;
break;
}
return(used);
}
void HandleServer(void)
{
Uint8 data[512];
int pos, len;
int used;
/* Has the connection been lost with the server? */
len = SDLNet_TCP_Recv(tcpsock, (char *)data, 512);
if ( len <= 0 ) {
SDLNet_TCP_DelSocket(socketset, tcpsock);
SDLNet_TCP_Close(tcpsock);
tcpsock = NULL;
termwin->AddText("Connection with server lost!\n");
} else {
pos = 0;
while ( len > 0 ) {
used = HandleServerData(&data[pos]);
pos += used;
len -= used;
if ( used == 0 ) {
/* We might lose data here.. oh well,
we got a corrupt packet from server
*/
len = 0;
}
}
}
}
void HandleClient(void)
{
int n;
n = SDLNet_UDP_RecvV(udpsock, packets);
while ( n-- > 0 ) {
if ( packets[n]->channel >= 0 ) {
termwin->AddText("[%s] ",
people[packets[n]->channel].name);
termwin->AddText((char *)packets[n]->data, packets[n]->len);
}
}
}
GUI_status HandleNet(void)
{
SDLNet_CheckSockets(socketset, 0);
if ( SDLNet_SocketReady(tcpsock) ) {
HandleServer();
}
if ( SDLNet_SocketReady(udpsock) ) {
HandleClient();
}
/* Redraw the screen if the window changed */
if ( termwin->Changed() ) {
return(GUI_REDRAW);
} else {
return(GUI_PASS);
}
}
void InitGUI(SDL_Surface *screen)
{
int x1, y1, y2;
SDL_Rect empty_rect = { 0, 0, 0, 0 };
GUI_Widget *widget;
gui = new GUI(screen);
/* Chat terminal window */
termwin = new GUI_TermWin(0, 0, 80*8, 50*8, NULL,NULL,CHAT_SCROLLBACK);
gui->AddWidget(termwin);
/* Send-line window */
y1 = termwin->H()+2;
sendwin = new GUI_TermWin(0, y1, 80*8, 1*8, NULL, SendKey, 0);
sendwin->AddText(CHAT_PROMPT);
gui->AddWidget(sendwin);
/* Add scroll buttons for main window */
y1 += sendwin->H()+2;
y2 = y1+images[IMAGE_SCROLL_UP]->h;
widget = new GUI_ScrollButtons(2, y1, images[IMAGE_SCROLL_UP],
empty_rect, 2, y2, images[IMAGE_SCROLL_DN],
SCROLLBAR_VERTICAL, termwin);
gui->AddWidget(widget);
/* Add QUIT button */
x1 = (screen->w-images[IMAGE_QUIT]->w)/2;
y1 = sendwin->Y()+sendwin->H()+images[IMAGE_QUIT]->h/2;
widget = new GUI_Button(NULL, x1, y1, images[IMAGE_QUIT], NULL);
gui->AddWidget(widget);
/* That's all folks */
return;
}
extern "C"
void cleanup(int exitcode)
{
int i;
/* Clean up the GUI */
if ( gui ) {
delete gui;
gui = NULL;
}
/* Clean up any images we have */
for ( i=0; i<NUM_IMAGES; ++i ) {
if ( images[i] ) {
SDL_FreeSurface(images[i]);
images[i] = NULL;
}
}
/* Close the network connections */
if ( tcpsock != NULL ) {
SDLNet_TCP_Close(tcpsock);
tcpsock = NULL;
}
if ( udpsock != NULL ) {
SDLNet_UDP_Close(udpsock);
udpsock = NULL;
}
if ( socketset != NULL ) {
SDLNet_FreeSocketSet(socketset);
socketset = NULL;
}
if ( packets != NULL ) {
SDLNet_FreePacketV(packets);
packets = NULL;
}
SDLNet_Quit();
SDL_Quit();
exit(exitcode);
}
int main(int argc, char *argv[])
{
SDL_Surface *screen;
int i;
char *server;
IPaddress serverIP;
/* Check command line arguments */
if ( argv[1] == NULL ) {
fprintf(stderr, "Usage: %s <server>\n", argv[0]);
exit(1);
}
/* Initialize SDL */
if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
exit(1);
}
/* Set a 640x480 video mode -- allows 80x50 window using 8x8 font */
screen = SDL_SetVideoMode(640, 480, 0, SDL_SWSURFACE);
if ( screen == NULL ) {
fprintf(stderr, "Couldn't set video mode: %s\n",SDL_GetError());
SDL_Quit();
exit(1);
}
/* Initialize the network */
if ( SDLNet_Init() < 0 ) {
fprintf(stderr, "Couldn't initialize net: %s\n",
SDLNet_GetError());
SDL_Quit();
exit(1);
}
/* Get ready to initialize all of our data */
/* Load the display font and other images */
for ( i=0; i<NUM_IMAGES; ++i ) {
images[i] = NULL;
}
for ( i=0; i<NUM_IMAGES; ++i ) {
images[i] = SDL_LoadBMP(image_files[i]);
if ( images[i] == NULL ) {
fprintf(stderr, "Couldn't load '%s': %s\n",
image_files[i], SDL_GetError());
cleanup(2);
}
}
/* Go! */
InitGUI(screen);
/* Allocate a vector of packets for client messages */
packets = SDLNet_AllocPacketV(4, CHAT_PACKETSIZE);
if ( packets == NULL ) {
fprintf(stderr, "Couldn't allocate packets: Out of memory\n");
cleanup(2);
}
/* Connect to remote host and create UDP endpoint */
server = argv[1];
termwin->AddText("Connecting to %s ... ", server);
gui->Display();
SDLNet_ResolveHost(&serverIP, server, CHAT_PORT);
if ( serverIP.host == INADDR_NONE ) {
termwin->AddText("Couldn't resolve hostname\n");
} else {
/* If we fail, it's okay, the GUI shows the problem */
tcpsock = SDLNet_TCP_Open(&serverIP);
if ( tcpsock == NULL ) {
termwin->AddText("Connect failed\n");
} else {
termwin->AddText("Connected\n");
}
}
/* Try ports in the range {CHAT_PORT - CHAT_PORT+10} */
for ( i=0; (udpsock == NULL) && i<10; ++i ) {
udpsock = SDLNet_UDP_Open(CHAT_PORT+i);
}
if ( udpsock == NULL ) {
SDLNet_TCP_Close(tcpsock);
tcpsock = NULL;
termwin->AddText("Couldn't create UDP endpoint\n");
}
/* Allocate the socket set for polling the network */
socketset = SDLNet_AllocSocketSet(2);
if ( socketset == NULL ) {
fprintf(stderr, "Couldn't create socket set: %s\n",
SDLNet_GetError());
cleanup(2);
}
SDLNet_TCP_AddSocket(socketset, tcpsock);
SDLNet_UDP_AddSocket(socketset, udpsock);
/* Run the GUI, handling network data */
SendHello(argv[2]);
gui->Run(HandleNet);
cleanup(0);
/* Keep the compiler happy */
return(0);
}

54
SDL_net/src/chat.h Normal file
View file

@ -0,0 +1,54 @@
/*
CHAT: A chat client/server using the SDL example network library
Copyright (C) 1997-2009 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/* $Id: chat.h 4211 2008-12-08 00:27:32Z slouken $ */
/* Convert four letters into a number */
#define MAKE_NUM(A, B, C, D) (((A+B)<<8)|(C+D))
/* Defines for the chat client */
#define CHAT_SCROLLBACK 512 /* Save 512 lines in scrollback */
#define CHAT_PROMPT "> "
#define CHAT_PACKETSIZE 256 /* Maximum length of a message */
/* Defines shared between the server and client */
#define CHAT_PORT MAKE_NUM('C','H','A','T')
/* The protocol between the chat client and server */
#define CHAT_HELLO 0 /* 0+Port+len+name */
#define CHAT_HELLO_PORT 1
#define CHAT_HELLO_NLEN CHAT_HELLO_PORT+2
#define CHAT_HELLO_NAME CHAT_HELLO_NLEN+1
#define CHAT_ADD 1 /* 1+N+IP+Port+len+name */
#define CHAT_ADD_SLOT 1
#define CHAT_ADD_HOST CHAT_ADD_SLOT+1
#define CHAT_ADD_PORT CHAT_ADD_HOST+4
#define CHAT_ADD_NLEN CHAT_ADD_PORT+2
#define CHAT_ADD_NAME CHAT_ADD_NLEN+1
#define CHAT_DEL 2 /* 2+N */
#define CHAT_DEL_SLOT 1
#define CHAT_DEL_LEN CHAT_DEL_SLOT+1
#define CHAT_BYE 255 /* 255 */
#define CHAT_BYE_LEN 1
/* The maximum number of people who can talk at once */
#define CHAT_MAXPEOPLE 10

260
SDL_net/src/chatd.c Normal file
View file

@ -0,0 +1,260 @@
/*
CHATD: A chat server using the SDL example network library
Copyright (C) 1997-2009 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/* Note that this isn't necessarily the way to run a chat system.
This is designed to excercise the network code more than be really
functional.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "SDL.h"
#include "SDL_net.h"
#include "chat.h"
/* This is really easy. All we do is monitor connections */
static TCPsocket servsock = NULL;
static SDLNet_SocketSet socketset = NULL;
static struct {
int active;
TCPsocket sock;
IPaddress peer;
Uint8 name[256+1];
} people[CHAT_MAXPEOPLE];
void HandleServer(void)
{
TCPsocket newsock;
int which;
unsigned char data;
newsock = SDLNet_TCP_Accept(servsock);
if ( newsock == NULL ) {
return;
}
/* Look for unconnected person slot */
for ( which=0; which<CHAT_MAXPEOPLE; ++which ) {
if ( ! people[which].sock ) {
break;
}
}
if ( which == CHAT_MAXPEOPLE ) {
/* Look for inactive person slot */
for ( which=0; which<CHAT_MAXPEOPLE; ++which ) {
if ( people[which].sock && ! people[which].active ) {
/* Kick them out.. */
data = CHAT_BYE;
SDLNet_TCP_Send(people[which].sock, &data, 1);
SDLNet_TCP_DelSocket(socketset,
people[which].sock);
SDLNet_TCP_Close(people[which].sock);
#ifdef DEBUG
fprintf(stderr, "Killed inactive socket %d\n", which);
#endif
break;
}
}
}
if ( which == CHAT_MAXPEOPLE ) {
/* No more room... */
data = CHAT_BYE;
SDLNet_TCP_Send(newsock, &data, 1);
SDLNet_TCP_Close(newsock);
#ifdef DEBUG
fprintf(stderr, "Connection refused -- chat room full\n");
#endif
} else {
/* Add socket as an inactive person */
people[which].sock = newsock;
people[which].peer = *SDLNet_TCP_GetPeerAddress(newsock);
SDLNet_TCP_AddSocket(socketset, people[which].sock);
#ifdef DEBUG
fprintf(stderr, "New inactive socket %d\n", which);
#endif
}
}
/* Send a "new client" notification */
void SendNew(int about, int to)
{
char data[512];
int n;
n = strlen((char *)people[about].name)+1;
data[0] = CHAT_ADD;
data[CHAT_ADD_SLOT] = about;
memcpy(&data[CHAT_ADD_HOST], &people[about].peer.host, 4);
memcpy(&data[CHAT_ADD_PORT], &people[about].peer.port, 2);
data[CHAT_ADD_NLEN] = n;
memcpy(&data[CHAT_ADD_NAME], people[about].name, n);
SDLNet_TCP_Send(people[to].sock, data, CHAT_ADD_NAME+n);
}
void HandleClient(int which)
{
char data[512];
int i;
/* Has the connection been closed? */
if ( SDLNet_TCP_Recv(people[which].sock, data, 512) <= 0 ) {
#ifdef DEBUG
fprintf(stderr, "Closing socket %d (was%s active)\n",
which, people[which].active ? "" : " not");
#endif
/* Notify all active clients */
if ( people[which].active ) {
people[which].active = 0;
data[0] = CHAT_DEL;
data[CHAT_DEL_SLOT] = which;
for ( i=0; i<CHAT_MAXPEOPLE; ++i ) {
if ( people[i].active ) {
SDLNet_TCP_Send(people[i].sock,data,CHAT_DEL_LEN);
}
}
}
SDLNet_TCP_DelSocket(socketset, people[which].sock);
SDLNet_TCP_Close(people[which].sock);
people[which].sock = NULL;
} else {
switch (data[0]) {
case CHAT_HELLO: {
/* Yay! An active connection */
memcpy(&people[which].peer.port,
&data[CHAT_HELLO_PORT], 2);
memcpy(people[which].name,
&data[CHAT_HELLO_NAME], 256);
people[which].name[256] = 0;
#ifdef DEBUG
fprintf(stderr, "Activating socket %d (%s)\n",
which, people[which].name);
#endif
/* Notify all active clients */
for ( i=0; i<CHAT_MAXPEOPLE; ++i ) {
if ( people[i].active ) {
SendNew(which, i);
}
}
/* Notify about all active clients */
people[which].active = 1;
for ( i=0; i<CHAT_MAXPEOPLE; ++i ) {
if ( people[i].active ) {
SendNew(i, which);
}
}
}
break;
default: {
/* Unknown packet type?? */;
}
break;
}
}
}
static void cleanup(int exitcode)
{
if ( servsock != NULL ) {
SDLNet_TCP_Close(servsock);
servsock = NULL;
}
if ( socketset != NULL ) {
SDLNet_FreeSocketSet(socketset);
socketset = NULL;
}
SDLNet_Quit();
SDL_Quit();
exit(exitcode);
}
main(int argc, char *argv[])
{
IPaddress serverIP;
int i;
/* Initialize SDL */
if ( SDL_Init(0) < 0 ) {
fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
exit(1);
}
/* Initialize the network */
if ( SDLNet_Init() < 0 ) {
fprintf(stderr, "Couldn't initialize net: %s\n",
SDLNet_GetError());
SDL_Quit();
exit(1);
}
/* Initialize the channels */
for ( i=0; i<CHAT_MAXPEOPLE; ++i ) {
people[i].active = 0;
people[i].sock = NULL;
}
/* Allocate the socket set */
socketset = SDLNet_AllocSocketSet(CHAT_MAXPEOPLE+1);
if ( socketset == NULL ) {
fprintf(stderr, "Couldn't create socket set: %s\n",
SDLNet_GetError());
cleanup(2);
}
/* Create the server socket */
SDLNet_ResolveHost(&serverIP, NULL, CHAT_PORT);
printf("Server IP: %x, %d\n", serverIP.host, serverIP.port);
servsock = SDLNet_TCP_Open(&serverIP);
if ( servsock == NULL ) {
fprintf(stderr, "Couldn't create server socket: %s\n",
SDLNet_GetError());
cleanup(2);
}
SDLNet_TCP_AddSocket(socketset, servsock);
/* Loop, waiting for network events */
for ( ; ; ) {
/* Wait for events */
SDLNet_CheckSockets(socketset, ~0);
/* Check for new connections */
if ( SDLNet_SocketReady(servsock) ) {
HandleServer();
}
/* Check for events on existing clients */
for ( i=0; i<CHAT_MAXPEOPLE; ++i ) {
if ( SDLNet_SocketReady(people[i].sock) ) {
HandleClient(i);
}
}
}
cleanup(0);
/* Not reached, but fixes compiler warnings */
return 0;
}

1555
SDL_net/src/config.guess vendored Normal file

File diff suppressed because it is too large Load diff

1685
SDL_net/src/config.sub vendored Normal file

File diff suppressed because it is too large Load diff

134
SDL_net/src/configure.in Normal file
View file

@ -0,0 +1,134 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(README)
dnl Set various version strings - taken gratefully from the GTk sources
# Making releases:
# MICRO_VERSION += 1;
# INTERFACE_AGE += 1;
# BINARY_AGE += 1;
# if any functions have been added, set INTERFACE_AGE to 0.
# if backwards compatibility has been broken,
# set BINARY_AGE and INTERFACE_AGE to 0.
MAJOR_VERSION=1
MINOR_VERSION=2
MICRO_VERSION=7
INTERFACE_AGE=7
BINARY_AGE=7
VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION
AC_SUBST(MAJOR_VERSION)
AC_SUBST(MINOR_VERSION)
AC_SUBST(MICRO_VERSION)
AC_SUBST(INTERFACE_AGE)
AC_SUBST(BINARY_AGE)
AC_SUBST(VERSION)
# libtool versioning
LT_RELEASE=$MAJOR_VERSION.$MINOR_VERSION
LT_CURRENT=`expr $MICRO_VERSION - $INTERFACE_AGE`
LT_REVISION=$INTERFACE_AGE
LT_AGE=`expr $BINARY_AGE - $INTERFACE_AGE`
AC_SUBST(LT_RELEASE)
AC_SUBST(LT_CURRENT)
AC_SUBST(LT_REVISION)
AC_SUBST(LT_AGE)
dnl Detect the canonical build and host environments
AC_CANONICAL_HOST
dnl Setup for automake
AM_INIT_AUTOMAKE(SDL_net, $VERSION)
dnl Check for tools
AC_LIBTOOL_WIN32_DLL
AM_PROG_LIBTOOL
AC_PROG_CC
AC_PROG_CXX
AC_PROG_INSTALL
AC_PROG_MAKE_SET
if test -z "$host_alias"; then
hostaliaswindres=
else
hostaliaswindres="$host_alias-windres"
fi
AC_CHECK_PROGS(WINDRES, [windres $hostaliaswindres $host_os-windres])
case "$host" in
*-*-beos*)
ac_default_prefix=/boot/develop/tools/gnupro
;;
*-*-cygwin* | *-*-mingw32*)
if test "$build" != "$host"; then # cross-compiling
# Default cross-compile location
ac_default_prefix=/usr/local/cross-tools/i386-mingw32
else
# Look for the location of the tools and install there
if test "$BUILD_PREFIX" != ""; then
ac_default_prefix=$BUILD_PREFIX
fi
fi
if test x$WINDRES != x; then
use_version_rc=true
fi
;;
esac
AM_CONDITIONAL(USE_VERSION_RC, test x$use_version_rc = xtrue)
dnl Figure out which networking libraries to use
case "$host" in
*-*-cygwin* | *-*-mingw32*)
INETLIB="-lwsock32"
;;
sparc*-*-solaris*)
INETLIB="-lsocket -lnsl"
;;
*-*-qnx*)
INETLIB="-lsocket"
;;
*-*-beos*)
INETLIB=""
;;
*)
INETLIB=""
;;
esac
AC_SUBST(INETLIB)
dnl Check for SDL
SDL_VERSION=1.2.4
AM_PATH_SDL($SDL_VERSION,
:,
AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!])
)
CFLAGS="$CFLAGS $SDL_CFLAGS"
LIBS="$LIBS $SDL_LIBS"
dnl Check for GUI library for the chat client
have_GUI=no
AC_ARG_ENABLE(gui,
[ --enable-gui Try to build the GUI test programs [default=yes]],
, enable_gui=yes)
if test x$enable_gui = xyes; then
AC_CHECK_LIB(GUI, GUI_Create, have_GUI=yes)
if test x$have_GUI != xyes; then
AC_MSG_WARN([*** Can't find the GUI library - not building test programs
The GUI library can be found at:
http://www.libsdl.org/projects/GUIlib/
])
fi
fi
AM_CONDITIONAL(HAVE_GUI_LIB, test x$have_GUI = xyes)
dnl C++ flags are the same as the C flags
CXXFLAGS="$CXXFLAGS $CFLAGS"
AC_SUBST([WINDRES])
# Finally create all the generated files
AC_OUTPUT([
Makefile SDL_net.spec SDL_net.qpg
])

6864
SDL_net/src/ltmain.sh Normal file

File diff suppressed because it is too large Load diff