BASIC

Author Topic: Networking for Cowards - Part 2 - Session detection  (Read 16042 times)

Offline Kitty Hello

  • code monkey
  • Administrator
  • Prof. Inline
  • *******
  • Posts: 10667
  • here on my island the sea says 'hello'
    • View Profile
    • http://www.glbasic.com
OK, in this part of the tutorial "networking for cowards" we deal with sesstion detection. The main aim is to find a server in our LAN or the internet without having the user to type an IP address in some box.

LAN
The first thing we try is in our local network. That's pretty easy, because every network segment has a "broadcast" address. That is an IP address where you can send a UDP request to, and the request will be sent to _all_ computers connected to this network segment. Segment means, that it will stop at a router.

So, in order to find a server, we send a broadcast message "where are you" and wait for a resonse from the server.

First, we need 2 global ports and an application specific string.
Code: GLBasic [Select]
// 27910 = NET... commands
GLOBAL port_server% = 27911 // UDP for broadcasts
GLOBAL port_client% = 27912 // use a different one to enable 2 processes on one machine (debug on one computer)
GLOBAL session$ = "my_program_name" // a session name -> could change that for a session list
 


Code: GLBasic [Select]
// --------------------------------------------
// find a session using a broadcast
// --------------------------------------------
FUNCTION FindSession$:
        LOCAL sock%, ip$
        sock% = SOCK_UDPOPEN(port_client%) // open UDP client port (send broadcast port)
        // Uh-oh. Port is still locked from old instance (happens on iPhone sometimes)
        IF sock% <0
                SLEEP 2000
                RETURN ""
        ENDIF

        // find my own IP
        ip$ = SOCK_GETIP$(SOCK_GETIP(""))
        LOCAL ip_broadcast% = SOCK_GETIP("255.255.255.255") // 255.255.255.255 is the broadcast address of a network segment

        STDOUT "find session\n"
        FOR retry% = 1 TO 3 // retry some times - mostly works at 1st try
                LOCAL rv%, msg$
                rv% = SOCK_UDPSEND(sock%, session$+"\n"+ip$, ip_broadcast%, port_server%) // send the request
                IF rv% = -1
                        STDOUT "SOCK_UDPSEND -1\n"
                        BREAK
                ENDIF

                // wait for a response
                FOR reread% = 1 TO 10
                        rv% = SOCK_RECV(sock%, msg$, 128)
                        IF rv%>0
                                SOCK_CLOSE(sock%)
                                STDOUT "server at"+msg$+"\n"
                                RETURN msg$ // return what the server said
                        ENDIF

                        IF rv% = -1
                                STDOUT "SOCK_RECV -1\n" // connection error!
                                GOTO failed
                        ENDIF

                        IF rv% = -2 // would block, try again later
                                STDOUT "."
                                SLEEP 100
                        ENDIF
                NEXT

                // inform about multiple read loops (usually one is enough)
                SLEEP 200
        NEXT

        STDOUT "timed out\n"
        @failed:

        SOCK_CLOSE(sock%)
        RETURN ""
ENDFUNCTION
 


The server should eventually read that port and replay with "I'm here" or so.
Code: GLBasic [Select]
// --------------------------------------------
// Wait for a client broadcasting a "Where are you" message.
// Then return the current IP address, so the client
// could connect.
// --------------------------------------------
FUNCTION AnnounceSession: bClose%
STATIC sock%
STATIC serverip$

        IF bClose% AND sock% // request to shut down
                SOCK_CLOSE(sock%)
                sock=0
                RETURN
        ENDIF

        IF sock% = 0
                serverip$ = SOCK_GETIP$(SOCK_GETIP("")) // open the listening port
                sock% = SOCK_UDPOPEN(port_server%)
                IF sock% <0
                        STDERR "can't host - port locked?\n"
                        END
                ENDIF
        ENDIF

        // wait for a request
        LOCAL rv%, msg$
        rv% = SOCK_RECV(sock%, msg$, 512)
        IF rv% > 0
                STDOUT "incomming broadcast, session: "+msg$+"\n"

                // compare session
                LOCAL pos% = INSTR(msg$, "\n")
                IF pos%>0
                        IF MID$(msg$, 0, pos%) = session$
                                LOCAL clientip$ = MID$(msg$, pos%+1, -1)
                                LOCAL clientip% = SOCK_GETIP(clientip$)
                                // reply
                                STDOUT "client accepted\n"

                                // send twice - just to be sure
                                SOCK_UDPSEND(sock%, serverip$, clientip%, port_client%)
                                SLEEP 3
                                SOCK_UDPSEND(sock%, serverip$, clientip%, port_client%)
                        ENDIF
                ENDIF
        ENDIF

        IF rv=-1 // error -> reconnect
                STDOUT "announce_session - error. Try reconnect\n"
                SOCK_CLOSE(sock%)
                sock% = 0 // display error message here. (Wait for a few seconds, then retry)
        ENDIF
ENDFUNCTION
 

In out game we would use it like:

Code: GLBasic [Select]
full_again:

        IF SOCK_INIT()=FALSE
                STDERR "sock init failed\n"
                PRINT lang$("No Wifi", "Kein WLan"),32,screeny-fy-8; SHOWSCREEN
                WHILE TRUE; SLEEP 1000; WEND
        ENDIF


        session_ip$ = FindSession$()
        IF LEN(session_ip$)>4 AND NETJOINGAME(session_ip$, 0)
                gIsServer%=FALSE
        ELSE
                PRINT "Hosting session", 32, 32; SHOWSCREEN
                IF NETHOSTGAME(0)
                        gIsServer%=TRUE
                        SLEEP 100
                ELSE
                        STDERR "can't host, port seems still open\n"
                        PRINT "Port busy, please wait.", 32,32; SHOOWSCREEN
                        NETSHUTDOWN
                        SLEEP 2000
                        GOTO full_again
                ENDIF
        ENDIF

// ... ok, the game is connected and on.
 


INTERNET
OK, long time no update. Here's how to find a seccion over the internet using a very simple php script:
(Uses an .ini file - no database)

Code: GLBasic [Select]
<?php
  // http://www.GLBasic.com/netsession.php?session=test&host=0
        // host= 0 -> find server - return server IP if there's a session
        // host= 1 -> host new session - returns "HOSTED" on success
        // host=-1 -> stop session - I forgot if it returns something usefull

    $ses = $_GET['session'];
    session_id('glbs'.$ses);
    $host = (int)$_GET['host'];
   

    $timeout = 15*60; // [sec]
    session_start();

    if(isset($_GET['host']) && $host == 1)
    {
        // if(PHP <= 4.0.6) use $HTTP_SESSION_VARS
        $_SESSION[$ses] = $_SERVER['REMOTE_ADDR'];
        $_SESSION[$ses.'@TimE'] = time();
        echo 'HOSTED';
    }
    else if($host == -1) // stop a session
    {
        $_SESSION[$ses] = '0';
        $_SESSION[$ses.'@TimE'] = 0;
        echo 'STOPPED';
    }
    else // find a session
    {
        if (!isset($_SESSION[$ses]) || !isset($_SESSION[$ses.'@TimE']) || (int)$_SESSION[$ses.'@TimE'] < (time()-$timeout) )
        {
            echo '0';
        }
        else
        {
            // seems a good session,
            echo $_SESSION[$_GET['session']];
        }
    }
?>
 

Please feel free to use my script, but notify me, please. I might put filters in, when traffic rises to steep.

The GLBasic side of the script is easy as:
Code: GLBasic [Select]

FUNCTION FindSessionINET$:
LOCAL ip$
        // see if there is already a session
        ip$ = NETWEBGET$("www.glbasic.com", "/netsession.php?session="+gSession$+"&host=0", 0, 256)

        IF LEN(ip$)>4 THEN RETURN ip$
        RETURN ""
ENDFUNCTION


// Announce session in INET
// true/false
FUNCTION AnnounceSessionINET%: bClose%
LOCAL ip$
        IF bClose% = FALSE
                ip$ = NETWEBGET$("www.glbasic.com", "/netsession.php?session="+gSession$+"&host=1", 0, 256)
                IF ip$="HOSTED" THEN RETURN TRUE
                RETURN FALSE
        ELSE
                // tell the server to stop it
                NETWEBGET$("www.glbasic.com", "/netsession.php?session="+gSession$+"&host=-1", 0, 256)
                RETURN TRUE
        ENDIF
ENDFUNCTION
 


... See the updated version here:
http://www.glbasic.com/forum/index.php?topic=2779.msg95840#msg95840


« Last Edit: 2016-Oct-21 by Kitty Hello »

Offline Schranz0r

  • Premium User :)
  • Administrator
  • Prof. Inline
  • *******
  • Posts: 4977
  • O Rly?
    • View Profile
WOW :nw:
I <3 DGArray's :D

PC:
AMD RYzen 7 1700 @3.9Ghz, 16GB HyperX Fury 2666Mhz Ram, ASUS ROG GTX 1060 STRIX 6GB, Windows 10 Pro 64Bit, MSi Tomahawk B350 Mainboard

Offline FutureCow

  • HelpEditor
  • Prof. Inline
  • ******
  • Posts: 680
    • View Profile
Thanks Gernot!!!

Offline bigsofty

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 2558
    • View Profile
Arg, what happened to the 2ND lesson? :rant:
Cheers,

Ian.

“It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration.”
(E. W. Dijkstra)

Offline bigsofty

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 2558
    • View Profile
Can anyone see Gernots post in this thread, Ive noticed a few of his posts are now blank when I read them?
Cheers,

Ian.

“It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration.”
(E. W. Dijkstra)

Offline Hemlos

  • To boldy go where no pixel has gone before!
  • Global Moderator
  • Prof. Inline
  • *******
  • Posts: 1579
  • Particle Hawk
    • View Profile
Its blank.
Volume_of_Earth(km^3) = 4/3*3.14*POW(6371.392896,3)

Offline FutureCow

  • HelpEditor
  • Prof. Inline
  • ******
  • Posts: 680
    • View Profile
There are various bits of threads that disappeared when the forum moved to the new layout. It's not just Gernot's posts though that are affected.
eg. The first post in this thread by Schranz0r http://www.glbasic.com/forum/index.php?topic=1103.0
« Last Edit: 2009-Nov-28 by FutureCow »

Offline bigsofty

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 2558
    • View Profile
Damn board hackers... now this sucks!  Gernot do you still have this on backup or did anyone save this page?  :rtfm:
Cheers,

Ian.

“It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration.”
(E. W. Dijkstra)

Offline Kitty Hello

  • code monkey
  • Administrator
  • Prof. Inline
  • *******
  • Posts: 10667
  • here on my island the sea says 'hello'
    • View Profile
    • http://www.glbasic.com
Schranz - can we have the old board in a new database so we can copy/paste some threads manually??

Offline codegit

  • Dr. Type
  • ****
  • Posts: 270
    • View Profile
Does anybody have a copy of the original code posted by Gernot? Please!!!  =D
------------------------------------------
1 X Acer TravelMate 4270, laptop, XP PRO
1 X Dell Studio 17 laptop, Windows 7
1 X MacBook Pro 2,2 GHz Core 2 Duo, 2 GB RAM, 160 GB HDD, 9400M
2 X iTouch
1 X HTC Desire (Android 2.1)
iPad soon to be added

Offline FutureCow

  • HelpEditor
  • Prof. Inline
  • ******
  • Posts: 680
    • View Profile
Just a thought. Have a look in the samples you get with GLBasic. I just found there's some networking ones there which might show you how to do whatever networking stuff you're looking for.

Offline bigsofty

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 2558
    • View Profile
For myself, code only, is a pretty weak substitute for the original text. As it is a new subject to many, a good explanation is required in interpret the accompanying examples.  :(
Cheers,

Ian.

“It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration.”
(E. W. Dijkstra)

Offline bigsofty

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 2558
    • View Profile
Excellent, many thanks for repairing the tutorial!  :good:
Cheers,

Ian.

“It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration.”
(E. W. Dijkstra)

Offline codegit

  • Dr. Type
  • ****
  • Posts: 270
    • View Profile
Thank you  8)
------------------------------------------
1 X Acer TravelMate 4270, laptop, XP PRO
1 X Dell Studio 17 laptop, Windows 7
1 X MacBook Pro 2,2 GHz Core 2 Duo, 2 GB RAM, 160 GB HDD, 9400M
2 X iTouch
1 X HTC Desire (Android 2.1)
iPad soon to be added

Offline Kitty Hello

  • code monkey
  • Administrator
  • Prof. Inline
  • *******
  • Posts: 10667
  • here on my island the sea says 'hello'
    • View Profile
    • http://www.glbasic.com
Here's an updated version that uses an extended version on my server. Feel free to directly use the GLBAsic.com server interface for your game, but please tell me before you release it.

Code: GLBasic [Select]

// --------------------------------- //
// Start: Wednesday, August 27, 2008
// IDE Version: 5.360


// ------------------------------------
// FIND A SESSION ON LAN or INTERNET
// ------------------------------------
// Open firewall ports:
// 27910 TCP - game data transfer - MUST open this one outgoing, and (if you're the server) ingoing
// 27911 UDP - LAN session anouncement, incomming (server)
// 27912 UDP - LAN session anouncement, incomming (client)

// *** HOW TO USE ***
//      SessionInit("MyGame", "Chatroom-ID", "UserName", bInternetYesNo%)
//      WHILE TRUE
//              gPlayer% = SessionKeepAlive(TRUE)   // NETCREATEPLAYER("scribble")
//              IF gPlayer<>0 THEN NETSENDMSG(gPlayer%, 0, "Hello World")
//              UpdateGame()
//      WEND

// *** Internals ***
// The app will try to find a session (chatroom). If a sever exists, it connects.
// If no server exists, it will start a server and ...
// -LAN-mode:      Read from a UDP port for incomming client requests.
// -Internet-mode: Send glbasic.com the IP of this device, registering app name, session-ID.
//                 The client in internet mode will connect to glbasic.com and gain the app-server's IP
//                 and connect to it.

// Set this SUB if you want to get notified on errors
GLOBAL gSessionErrorSUB$    = "" // this SUB is called when an error occours.
GLOBAL gSessionErrorString$ = "" // here you find the error details.




GLOBAL gSessionIsInternet% = FALSE // TRUE: Internet, FALSE: LAN
GLOBAL gSessionIsServer% = FALSE
GLOBAL gSession$ = "INVALID"
GLOBAL gSession_port_nethost% = 27910 // TCP - you must ***open this port***  for incomming connections on your firewall and router, if this computer is the server.
GLOBAL gSession_port_server% = 27911  // UDP - server reads from to this port in LAN network for incomming clients.
GLOBAL gSession_port_client% = 27912  // UDP - client reads from this port in LAN when finding the server.
GLOBAL gSession_net_player% = 0 // NET player id
GLOBAL gSession_net_playername$ = "joe"


// --------------------------------------------
// init the session
// App$     - your app name
// Session$ - the name of the session to find/host (consider that as a chatroom)
// App$+Session$ must be > 10 chars and < 24 chars! Otherwise you get the return value -1 in FindSessionINET$
// port_client - 0:default. UDP port for local LAN broadcasts
// port_server - 0:default. UDP port the server listens to
// --------------------------------------------
FUNCTION SessionInit: App$, Session$, PlayerName$, bIsInternet%, port_nethost%=0, port_client%=0, port_server%=0

        STDOUT "session init "+App$+"/"+Session$+"/"+PlayerName$+". Internet: "+bIsInternet%+"\n"

        // just to be sure, close connections
        SessionKeepAlive(FALSE)

        // make unique session string, with safe characters
        gSession$ = LEFT$(UCASE$(App$) + "-" + URLENCODE$(UCASE$(Session$)), 24)

        gSession_net_playername$ = PlayerName$

        gSessionIsInternet% = bIsInternet%

        IF port_nethost>0 THEN gSession_port_nethost% = port_nethost%
        IF port_client>0  THEN gSession_port_client%  = port_client%
        IF port_server>0  THEN gSession_port_server%  = port_server%

        // just to be sure
        SOCK_INIT()
ENDFUNCTION




// --------------------------------------------
// find a session using a broadcast
// returns "" - still searching
//         IP address - server found
// --------------------------------------------
FUNCTION SessionFindLAN$:
        LOCAL sock%, ip$
        STDOUT "open udp: "+gSession_port_client%+"\n"

        sock% = SOCK_UDPOPEN(gSession_port_client%)
        // Uh-oh. Port is still locked
        IF sock% <0
                SessionError("Can't open UDP port "+gSession_port_client%)
                STDOUT NETGETLASTERROR$() + "\n"
                STDOUT "can't open udp port (can't connect). Might be still locked from old session\n"
                RETURN ""
        ENDIF

        // find my own IP
        ip$ = SOCK_GETIP$(SOCK_GETHOSTIP$(""))
        LOCAL ip_broadcast$ = SOCK_GETHOSTIP$("255.255.255.255")

        STDOUT "find session\n"
        FOR retry% = 1 TO 3
                LOCAL rv%, msg$
                rv% = SOCK_UDPSEND(sock%, gSession$+"\n"+ip$, ip_broadcast$, gSession_port_server%)
                IF rv% = -1
                        STDOUT NETGETLASTERROR$() + "\n"
                        STDOUT "SOCK_UDPSEND -1\n"
                        BREAK
                ENDIF

                // wait for a response
                FOR reread% = 1 TO 5
                        rv% = SOCK_RECV(sock%, msg$, 128)
                        IF rv%>0
                                SOCK_CLOSE(sock%)
                                STDOUT "server at"+msg$+"\n"
                                RETURN msg$ // return what the server said
                        ENDIF

                        IF rv% = -1
                                STDOUT "SOCK_RECV -1\n"
                                GOTO failed
                        ENDIF

                        IF rv% = -2 // would block, try again later
                                STDOUT "."
                                SLEEP 100
                        ENDIF
                NEXT

                // inform about multiple read loops (usually one is enough)
                SLEEP 200
        NEXT

        STDOUT "timed out\n"
        @failed:

        SOCK_CLOSE(sock%)
        RETURN ""
ENDFUNCTION



// --------------------------------------------
// Wait for a client broadcasting a "Where are you" message.
// Then return the current IP address, so the client
// could connect.
// does not return any value
// --------------------------------------------
FUNCTION SessionAnnounceLAN%: bClose%
STATIC sock%
STATIC serverip$

        IF bClose%
                IF sock% THEN SOCK_CLOSE(sock%)
                sock=0
                RETURN
        ENDIF

        IF sock% = 0
                serverip$ = SOCK_GETIP$(SOCK_GETHOSTIP$(""))
                STDOUT "open udp: "+gSession_port_server%+"\n"
                sock% = SOCK_UDPOPEN(gSession_port_server%)
                IF sock% <0
                        STDOUT NETGETLASTERROR$() + "\n"
                        STDERR "can't host - port locked?\n"
                        RETURN
                ENDIF
        ENDIF

        // wait for a request
        LOCAL rv%, msg$
        rv% = SOCK_RECV(sock%, msg$, 512)
        IF rv% > 0
                STDOUT "incomming LAN broadcast, session: "+msg$+"\n"

                // compare session
                LOCAL pos% = INSTR(msg$, "\n")
                IF pos%>0
                        IF MID$(msg$, 0, pos%) = gSession$
                                LOCAL clientip$ = MID$(msg$, pos%+1, -1)
                                LOCAL clientip_binary$ = SOCK_GETHOSTIP$(clientip$)
                                // reply
                                STDOUT "client accepted\n"

                                // send twice - just to be sure
                                SOCK_UDPSEND(sock%, serverip$, clientip_binary$, gSession_port_client%)
                                SLEEP 3
                                SOCK_UDPSEND(sock%, serverip$, clientip_binary$, gSession_port_client%)
                        ENDIF
                ENDIF
        ENDIF

        IF rv=-1 // error -> reconnect
                SessionError("Can't announce session. Try to reconnect.")
                STDOUT "announce_session - error. Try reconnect\n"
                SOCK_CLOSE(sock%)
                sock% = 0
        ENDIF
ENDFUNCTION


FUNCTION SessionFindINET$:
LOCAL ip$
        // see if there is already a session
        ip$ = NETWEBGET$("www.glbasic.com", "/netsession.php?session="+gSession$+"&host=0", 0, 256)

        STDOUT "Find internet session: "+ip$+"\n"

        IF LEN(ip$)>4 THEN RETURN ip$
        RETURN ""
ENDFUNCTION


// Announce session in INET
// true/false
FUNCTION SessionAnnounceINET%: bClose%
LOCAL ip$
STATIC bIsOpen%=FALSE
STATIC time_next_annc = 0 // don't connect to internet on every function call

        IF bClose% = FALSE
                bIsOpen% = FALSE

                LOCAL now =GETTIMERALL()
                IF now>time_next_annc
                        ip$ = NETWEBGET$("www.glbasic.com", "/netsession.php?session="+gSession$+"&host=1", 0, 256)
                        STDOUT "internet hosting game: "+ip$+"\n"
                        IF ip$="HOSTED"
                                bIsOpen% = TRUE
                                time_next_annc = GETTIMERALL() + 5 * 60 * 1000
                        ELSE
                                SessionError("Can't announce in internet.")
                                STDOUT NETGETLASTERROR$() + "\n"
                        ENDIF
                ENDIF

                RETURN bIsOpen%
        ELSE
                // tell the server to stop it
                IF bIsOpen%
                        ip$=NETWEBGET$("www.glbasic.com", "/netsession.php?session="+gSession$+"&host=-1", 0, 256)
                        STDOUT "Stopped hosting internet game: "+ip$+"\n"
                ENDIF
                bIsOpen% = FALSE
                time_next_annc = 0
                RETURN TRUE
        ENDIF
ENDFUNCTION




// just call this function every now and then to get going
// this returns your player-ID for NETSEND and such...
FUNCTION SessionKeepAlive%: bKeepAlive%
        STATIC bConnected% = FALSE
        IF NOT bKeepAlive // Shutdown
                STDOUT "Session shutdown\n"
                IF gSessionIsInternet
                        SessionAnnounceINET(TRUE)
                ELSE
                        SessionAnnounceLAN(TRUE)
                ENDIF
                bConnected = FALSE
                NETSHUTDOWN
                SOCK_SHUTDOWN
                gSession_net_player = 0
                gSessionIsServer% = FALSE
                RETURN
        ENDIF


        IF NOT bConnected% // join session
                gSessionIsServer% = FALSE
                gSession_net_player%=0
                LOCAL ip$
                IF gSessionIsInternet
                        ip$ = SessionFindINET$()
                ELSE
                        ip$ = SessionFindLAN$()
                ENDIF

                IF LEN(ip$)>4
                        STDOUT "found sesstion. Try to NETJOINGAME "+ip$+":"+gSession_port_nethost%+"...\n"
                        IF NETJOINGAME(ip$, gSession_port_nethost%)
                                STDOUT "...OK\n"
                                bConnected% = TRUE

                                // STDOUT "Number of players: "+NETNUMPLAYERS() + "\n"
                        ELSE
                                SessionError("Failed to join game session at "+ip$+":"+gSession_port_nethost%)
                                STDOUT NETGETLASTERROR$() + "\n"
                        ENDIF
                ENDIF
        ENDIF

        IF NOT bConnected%
                STDOUT "Trying to host a session...\n"
                gSession_net_player%=0
                bConnected% = NETHOSTGAME(gSession_port_nethost%)
                IF bConnected%
                        NETALLOWJOINING TRUE
                        gSessionIsServer% = TRUE
                       
                        // See if we can be reached from the internet
                        IF gSessionIsInternet
                                LOCAL isok$ = NETWEBGET$("www.glbasic.com", "/netsession.php?ping="+gSession_port_nethost%, 0, 256)
                                IF LEFT$(isok$, 2) <> "OK"
                                        SessionError("FIREWALL blocked port "+gSession_port_nethost%)
                                        STDOUT isok$+"\n"
                                ELSE
                                        STDOUT "Firewall post "+gSession_port_nethost%+" is open. Clients can connect.\n"
                                ENDIF
                        ENDIF
                ENDIF
        ENDIF


        IF bConnected% // announce session
                IF gSessionIsInternet
                        SessionAnnounceINET(FALSE)
                ELSE
                        SessionAnnounceLAN(FALSE)
                ENDIF

                IF NOT NETISACTIVE()
                        gSession_net_player%=0
                        bConnected=FALSE
                ENDIF
        ENDIF

        // no player created
        IF bConnected% AND gSession_net_player% = 0
                gSession_net_player% = NETCREATEPLAYER(gSession_net_playername$)
                STDOUT "created player"+gSession_net_player%+"\n"
        ENDIF


        RETURN gSession_net_player%

ENDFUNCTION



FUNCTION SessionError%: err$
        STDOUT "ERROR: "+err$+"\n"
        gSessionErrorString$ = err$
        CALLBYNAME( gSessionErrorSUB$)
ENDFUNCTION