views:

355

answers:

2

Here is my code:

import java.net.*;
import java.io.*;
import java.util.*;
import org.jibble.pircbot.*;

public class WebSocket
{
    public static int port = 12345;

    public static ArrayList<WebSocketClient> clients = new ArrayList<WebSocketClient>();
    public static ArrayList<Boolean> handshakes = new ArrayList<Boolean>();
    public static ArrayList<String> nicknames = new ArrayList<String>();
    public static ArrayList<String> channels = new ArrayList<String>();
    public static int indexNum;

    public static void main(String args[])
    {
        try
        {
            ServerSocket ss = new ServerSocket(WebSocket.port);
            WebSocket.console("Created socket on port " + WebSocket.port);

            while (true)
            {
                Socket s = ss.accept();
                WebSocket.console("New Client connecting...");

                WebSocket.handshakes.add(WebSocket.indexNum,false);
                WebSocket.nicknames.add(WebSocket.indexNum,"");
                WebSocket.channels.add(WebSocket.indexNum,"");
                WebSocketClient p = new WebSocketClient(s,WebSocket.indexNum);
                Thread t = new Thread(
                        p);
                WebSocket.clients.add(WebSocket.indexNum,p);
                indexNum++;
                t.start();
            }
        }
        catch (Exception e)
        {
            WebSocket.console("ERROR - " + e.toString());

        }

    }

    public static void console(String msg)
    {
        Date date = new Date();
        System.out.println("[" + date.toString() + "] " + msg);
    }



}


class WebSocketClient implements Runnable
{
    private Socket s;
    private int iAm;

    private String socket_res = "";
    private String socket_host = "";
    private String socket_origin = "";

    protected String nick = "";
    protected String ircChan = "";

    WebSocketClient(Socket socket, int mynum)
    {
        s = socket;
        iAm = mynum;
    }

    public void run()
    {
        String client = s.getInetAddress().toString();
        WebSocket.console("Connection from " + client);
        IRCclient irc = new IRCclient(iAm);
        Thread t = new Thread(
                irc
                );
        try
        {
            Scanner in = new Scanner(s.getInputStream());
            PrintWriter out = new PrintWriter(s.getOutputStream(),true);

            while (true)
            {
                if (! in.hasNextLine()) continue;
                String input = in.nextLine().trim();
                if (input.isEmpty()) continue;
                // Lets work out what's wrong with our input
                if (input.length() > 3 && input.charAt(0) == 65533)
                {
                    input = input.substring(2);
                }
                WebSocket.console("< " + input);
                // Lets work out if they authenticate...
                if (WebSocket.handshakes.get(iAm) == false)
                {
                    checkForHandShake(input);
                    continue;
                }

                // Lets check for NICK:
                if (input.length() > 6 && input.substring(0,6).equals("NICK: "))
                {
                    nick = input.substring(6);
                    Random generator = new Random();
                    int rand = generator.nextInt();
                    WebSocket.console("I am known as " + nick);
                    WebSocket.nicknames.set(iAm, "bo-" + nick + rand);
                }

                if (input.length() > 9 && input.substring(0,9).equals("CHANNEL: "))
                {
                    ircChan = "bo-" + input.substring(9);
                    WebSocket.console("We will be joining " + ircChan);
                    WebSocket.channels.set(iAm, ircChan);
                }

                if (! ircChan.isEmpty() && ! nick.isEmpty() && irc.started == false)
                {
                    irc.chan = ircChan;
                    irc.nick = WebSocket.nicknames.get(iAm);
                    t.start();
                    continue;
                }
                else
                {
                    irc.msg(input);
                }
            }
        }
        catch (Exception e)
        {
            WebSocket.console(e.toString());
            e.printStackTrace();
        }
        t.stop();
        WebSocket.channels.remove(iAm);
        WebSocket.clients.remove(iAm);
        WebSocket.handshakes.remove(iAm);
        WebSocket.nicknames.remove(iAm);
        WebSocket.console("Closing connection from " + client);
    }

    private void checkForHandShake(String input)
    {
        // Check for HTML5 Socket
        getHeaders(input);

        if (! socket_res.isEmpty() && ! socket_host.isEmpty() && ! socket_origin.isEmpty())
        {
            send("HTTP/1.1 101 Web Socket Protocol Handshake\r\n" +
                                "Upgrade: WebSocket\r\n" +
                                "Connection: Upgrade\r\n" +
                                "WebSocket-Origin: " + socket_origin + "\r\n" +
                                "WebSocket-Location: ws://" + socket_host + "/\r\n\r\n",false);
            WebSocket.handshakes.set(iAm,true);
        }
        return;
    }

    private void getHeaders(String input)
    {
         if (input.length() >= 8 && input.substring(0,8).equals("Origin: "))
         {
             socket_origin = input.substring(8);
             return;
         }

         if (input.length() >= 6 && input.substring(0,6).equals("Host: "))
         {
             socket_host = input.substring(6);
             return;
         }

         if (input.length() >= 7 && input.substring(0,7).equals("Cookie:"))
         {
             socket_res = ".";
         }


         /*input = input.substring(4);
         socket_res = input.substring(0,input.indexOf(" HTTP"));
         input = input.substring(input.indexOf("Host:") + 6);
         socket_host = input.substring(0,input.indexOf("\r\n"));
         input = input.substring(input.indexOf("Origin:") + 8);
         socket_origin = input.substring(0,input.indexOf("\r\n"));*/
         return;
    }

    protected void send(String msg, boolean newline)
    {
        byte c0 = 0x00;
        byte c255 = (byte) 0xff;
        try
        {
            PrintWriter out = new PrintWriter(s.getOutputStream(),true);
            WebSocket.console("> " + msg);
            if (newline == true)
                msg = msg + "\n";

            out.print(msg + c255);
            out.flush();

        }
        catch (Exception e)
        {
            WebSocket.console(e.toString());
        }
    }

    protected void send(String msg)
    {
        try
        {
            WebSocket.console(">> " + msg);

            byte[] message = msg.getBytes();

            byte[] newmsg = new byte[message.length + 2];

            newmsg[0] = (byte)0x00;
            for (int i = 1; i <= message.length; i++)
            {
                newmsg[i] = message[i - 1];
            }
            newmsg[message.length + 1] = (byte)0xff;

            // This prints correctly..., apparently...
            System.out.println(Arrays.toString(newmsg));

            OutputStream socketOutputStream = s.getOutputStream();
            socketOutputStream.write(newmsg);
        }
        catch (Exception e)
        {
            WebSocket.console(e.toString());
        }
    }

    protected void send(String msg, boolean one, boolean two)
    {
        try
        {
            WebSocket.console(">> " + msg);

            byte[] message = msg.getBytes();

            byte[] newmsg = new byte[message.length+1];

            for (int i = 0; i < message.length; i++)
            {
                newmsg[i] = message[i];
            }
            newmsg[message.length] = (byte)0xff;

            // This prints correctly..., apparently...
            System.out.println(Arrays.toString(newmsg));

            OutputStream socketOutputStream = s.getOutputStream();
            socketOutputStream.write(newmsg);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }


}
class IRCclient implements Runnable
{
    protected String nick;
    protected String chan;
    protected int iAm;

    boolean started = false;

    IRCUser irc;

    IRCclient(int me)
    {
        iAm = me;
        irc = new IRCUser(iAm);
    }

    public void run()
    {
        WebSocket.console("Connecting to IRC...");
        started = true;
        irc.setNick(nick);
        irc.setVerbose(false);
        irc.connectToIRC(chan);
    }

    void msg(String input)
    {
       irc.sendMessage("#" + chan, input);
    }


}

class IRCUser extends PircBot
{
    int iAm;
    IRCUser(int me)
    {
        iAm = me;
    }

    public void setNick(String nick)
    {
        this.setName(nick);
    }

    public void connectToIRC(String chan)
    {
        try
        {
            this.connect("irc.appliedirc.com");
            this.joinChannel("#" + chan);
        }
        catch (Exception e)
        {
            WebSocket.console(e.toString());
        }

    }

    public void onMessage(String channel, String sender,String login, String hostname, String message)
    {
        // Lets send this message to me
        WebSocket.clients.get(iAm).send(message);

    }

}

Whenever I try to send the message to the browser (via Web Sockets), it complains that it doesn't start with 0x00 (which is a byte).

Any ideas?

Edit 19/02 - Added the entire code. I know it's real messy and not neat, but I want to get it functioning first.

Spend last two days trying to fix.

A: 

Does it happen on the very first message? or only on the subsequent ones? If the latter, there is something wrong with how you are terminating the first message ...

EJP
It sends the headers back, and then it's on the first message (The client disconnects after the invalid msg).
giggsey
Sorry no capiche. Sends the headers back *in response* to the 1st message, or before it?
EJP
Web Sockets work so that the client connects to ws://bla.com:11111. The client then sends some headers (HTTP version, domain, cookies, etc.). The server then achnolowledges these, and sends some back (pretty much the same one). Then the "handshake" is complete, and the normal communication can start.
giggsey
OK. One thing I don't like in your code is that you fetch the socket's output stream for every message. In general you should do that when you acquire the Socket, and store it in the same scope. In fact you could improve this code considerably by wrapping the output stream in a BufferedOutputStream. Then you could just call bos.write(0); bos.write(msg.getBytes()); bos.write(0xff); bos.flush() and get rid of all the array copying.
EJP
A: 

Could you check if the initial handshake was completed before sending frames? The handshake should end with two empty lines.

Tihauan
I've added all my code. I do complete the handshake like that. (\r\n\r\n)
giggsey