Rebol [
    title: "Peer to Peer Instant Messenger"
    date: 29-june-2008
    file: %instant-messenger.r
    purpose: {
        Exchange text messages directly via TCP/IP network port.  
        Taken from the tutorial at

connected: false
insert-event-func closedown: func [face event] [
    either event/type = 'close [
        if connected [
            insert port trim {
                AND RECONNECT.
            close port
            if mode/text = "Server Mode" [close listen]
    ] [event]

view/new center-face gui: layout [
    at 5x2  ; this code positions the following items in the GUI
    text bold "Save Chat" [
        filename: to-file request-file/title/file/save trim {
            Save file as:} "Save" %/c/chat.txt
        write filename display/text 
    text bold "Lookup IP" [
        parse read [
            thru  copy my-ip to 
        parse my-ip [
            thru "Your IP is " copy stripped-ip to end
        alert to-string rejoin [
            "External: " trim/all stripped-ip "  "
            "Internal: " read join dns:// read dns://
    text bold "Help" [
        alert {
        Enter the IP address and port number in the fields
        provided.  If you will listen for others to call you, 
        use the rotary button to select "Server Mode" (you
        must have an exposed IP address and/or an open port
        to accept an incoming chat).  Select "Client Mode" if
        you will connect to another's chat server (you can do
        that even if you're behind an unconfigured firewall, 
        router, etc.).  Click "Connect" to begin the chat. 
        To test the application on one machine, open two
        instances of the chat application, leave the IP set
        to "localhost" on both.  Set one instance to run as 
        server, and the other as client, then click connect.
        You can edit the chat text directly in the display
        area, and you can save the text to a local file.
    lab1: h3 "IP Address:"  IP: field "localhost" 102
    lab2: h3 "Port:" portspec: field "9083" 50
    mode: rotary 120 "Client Mode" "Server Mode" [
        either value = "Client Mode" [
            show lab1 show IP
            hide lab1 hide IP
    cnnct: button red "Connect" [
        hide cnnct
        either mode/text = "Client Mode" [
            if error? try [
                port: open/direct/lines/no-wait to-url rejoin [
                    "tcp://" IP/text ":" portspec/text]
            ][alert "Server is not responding." return]
            if error? try [
                listen: open/direct/lines/no-wait to-url rejoin [
                    "tcp://:" portspec/text]
                wait listen
                port: first listen
            ][alert "Server is already running." return]
        focus entry
        connected: true
        forever [
            wait port
            foreach msg any [copy port []] [
                display/text: rejoin [
                    ">>>  "msg newline display/text]
            show display
    return  display: area "" 537x500
    return  entry: field 428  ; the numbers are pixel sizes
    button "Send Text" [
        if connected [
            insert port entry/text focus entry
            display/text: rejoin [
                "<<<  " entry/text newline display/text]
            show display

show gui do-events