Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IRC example #11

Open
bennn opened this issue Jun 13, 2024 · 1 comment
Open

IRC example #11

bennn opened this issue Jun 13, 2024 · 1 comment

Comments

@bennn
Copy link
Member

bennn commented Jun 13, 2024

Here's the code from the Programming 8.2 paper:
https://programming-journal.org/2024/8/8/

choral-irc.zip

The most interesting parts seem to be IrcClientToServerHandler.ch and IrcServerToClientHandler.ch, and those both look like things Chorex can handle. Right?

@bennn
Copy link
Member Author

bennn commented Jun 13, 2024

Client To Server:

package choral.examples.irc;

import java.util.List;

public class IrcClientToServerHandler@(Client, Server)
        implements EventHandler@(Client, Server)<Message> {
    private EventQueue@Server<Message> serverQueue;
    private IrcChannel@(Client, Server) ch_AB;

    private ClientState@Client clientState;

    private ServerState@Server serverState;
    private long@Server clientId;

    public IrcClientToServerHandler(EventQueue@Server<Message> serverQueue,
                                    IrcChannel@(Client, Server) ch_AB,
                                    ClientState@Client clientState,
                                    ServerState@Server serverState,
                                    long@Server clientId) {
        this.serverQueue = serverQueue;
        this.ch_AB = ch_AB;

        this.clientState = clientState;

        this.serverState = serverState;
        this.clientId = clientId;
    }

    /**
     * One step of the event loop driven by the client's message queue. Only the
     * client initiates requests.
     */
    public void on(Message@Client msg) {
        Command@Client cmd = Util@Client.commandFromString(msg.getCommand());
        Util@Client.check(cmd != null@Client, "Expected a known message"@Client);

        switch (cmd) {
            case PING -> {
                PingMessage@Server ping = ch_AB.<PingMessage>tselect(
                    Util@Client.<PingMessage>as(msg));
                ServerUtil@Server.printRecv(serverState, clientId, ping);

                if (!serverState.isRegistered(clientId)) {{
                    serverQueue.enqueue(ServerUtil@Server.forwardNumeric(
                        serverState, Command@Server.ERR_NOTREGISTERED,
                        "*"@Server, "You must register first"@Server));
                }}
                else {
                    if (!ping.hasEnoughParams()) {
                        serverQueue.enqueue(ServerUtil@Server.forwardNumeric(
                            serverState, Command@Server.ERR_NEEDMOREPARAMS,
                            serverState.getNickname(clientId),
                            Util@Server.commandToString(Command@Server.PING),
                            "Need more parameters"@Server));
                    }
                    else {
                        serverQueue.enqueue(
                            ServerUtil@Server.<PongMessage>withSource(
                                new PongMessage@Server(
                                    serverState.getHostname(),
                                    ping.getToken()),
                                new Source@Server(
                                    serverState.getHostname())));
                    }
                }
            }

            case PONG -> {
                PongMessage@Server pong = ch_AB.<PongMessage>tselect(
                    Util@Client.<PongMessage>as(msg));
                ServerUtil@Server.printRecv(serverState, clientId, pong);
            }

            case NICK -> {
                NickMessage@Client cNick = Util@Client.<NickMessage>as(msg);
                NickMessage@Server sNick = ch_AB.<NickMessage>tselect(cNick);
                ServerUtil@Server.printRecv(serverState, clientId, sNick);

                if (!clientState.isRegistered()) {
                    clientState.setNickname(cNick.getNickname());
                }

                ServerUtil@Server.processNick(serverState, clientId, sNick);
            }

            case USER -> {
                UserMessage@Client cUser = Util@Client.<UserMessage>as(msg);
                UserMessage@Server sUser = ch_AB.<UserMessage>tselect(cUser);
                ServerUtil@Server.printRecv(serverState, clientId, sUser);

                if (!clientState.isRegistered()) {
                    clientState.setUsername(cUser.getUsername());
                    clientState.setRealname(cUser.getRealname());
                }

                if (serverState.isRegistered(clientId)) {{{{
                    serverQueue.enqueue(ServerUtil@Server.forwardNumeric(
                        serverState, Command@Server.ERR_ALREADYREGISTERED,
                        serverState.getNickname(clientId),
                        "You cannot register again"@Server));
                }}}}
                else {
                    if (!sUser.hasEnoughParams() ||
                        sUser.getRealname().trim().equals(""@Server)) {{{
                        serverQueue.enqueue(ServerUtil@Server.forwardNumeric(
                            serverState, Command@Server.ERR_NEEDMOREPARAMS,
                            "*"@Server,
                            Util@Server.commandToString(Command@Server.USER),
                            "Need more parameters"@Server));
                    }}}
                    else {
                        String@Server username = sUser.getUsername();
                        String@Server realname = sUser.getRealname();

                        if (Util@Server.validUsername(username)) {
                            serverState.setUsername(clientId, username);
                            serverState.setRealname(clientId, realname);

                            if (serverState.canRegister(clientId)) {
                                ServerUtil@Server.processWelcome(
                                    serverState, clientId);
                            }
                        }
                        else {{}}
                    }
                }
            }

            case JOIN -> {
                JoinMessage@Server join = ch_AB.<JoinMessage>tselect(
                    Util@Client.<JoinMessage>as(msg));
                ServerUtil@Server.printRecv(serverState, clientId, join);

                ServerUtil@Server.processJoin(serverState, clientId, join);
            }

            case PART -> {
                PartMessage@Server part = ch_AB.<PartMessage>tselect(
                    Util@Client.<PartMessage>as(msg));
                ServerUtil@Server.printRecv(serverState, clientId, part);

                ServerUtil@Server.processPart(serverState, clientId, part);
            }

            case PRIVMSG -> {
                PrivmsgMessage@Server privmsg = ch_AB.<PrivmsgMessage>tselect(
                    Util@Client.<PrivmsgMessage>as(msg));
                ServerUtil@Server.printRecv(serverState, clientId, privmsg);

                ServerUtil@Server.processPrivmsg(
                    serverState, clientId, privmsg);
            }

            case QUIT -> {
                QuitMessage@Server quit = ch_AB.<QuitMessage>tselect(
                    Util@Client.<QuitMessage>as(msg));
                ServerUtil@Server.printRecv(serverState, clientId, quit);

                ServerUtil@Server.processQuit(serverState, clientId, quit);
            }
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant