refactor: move navbar and footer to layout.tsx
This commit is contained in:
parent
c52e971b36
commit
66b780eaad
2
.gitignore
vendored
2
.gitignore
vendored
@ -39,3 +39,5 @@ yarn-error.log*
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
|
||||
/.idea
|
@ -1,6 +1,8 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Geist, Rokkitt } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import NavBar from "@/components/NavBar";
|
||||
import Footer from "@/components/Footer";
|
||||
|
||||
const geistSans = Geist({
|
||||
variable: "--font-geist",
|
||||
@ -25,9 +27,11 @@ export default function RootLayout({
|
||||
return (
|
||||
<html lang="en">
|
||||
<body
|
||||
className={`${geistSans.variable} ${rokkitt.variable} bg-stone-900 font-geist antialiased`}
|
||||
className={`${geistSans.variable} ${rokkitt.variable} flex flex-col gap-4 bg-stone-900 font-geist antialiased max-w-[700px] mx-auto p-4 pt-15`}
|
||||
>
|
||||
<NavBar />
|
||||
{children}
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
@ -1,25 +1,17 @@
|
||||
import NavBar from "@/components/NavBar";
|
||||
import Footer from "@/components/Footer";
|
||||
import Text from "@/components/blocks/Text";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className={"bg-stone-900 min-h-screen font-geist"}>
|
||||
<main
|
||||
className={"max-w-[700px] pt-15 flex flex-col gap-4 mx-auto w-full p-4"}
|
||||
>
|
||||
<NavBar />
|
||||
<Text>
|
||||
Welcome to an unofficial webpage about the Real Address Chat protocol.
|
||||
Here you can find clients, servers, and documentation on how to use
|
||||
RAC and its successor, WRAC.
|
||||
</Text>
|
||||
<Text>
|
||||
Want to add your project to Racinfo? Make a pull request on our
|
||||
official GitHub repository, and we’ll review it.
|
||||
</Text>
|
||||
<Footer />
|
||||
</main>
|
||||
</div>
|
||||
<main className={"flex flex-col gap-4 mx-auto w-full"}>
|
||||
<Text>
|
||||
Welcome to an unofficial webpage about the Real Address Chat protocol.
|
||||
Here you can find clients, servers, and documentation on how to use RAC
|
||||
and its successor, WRAC.
|
||||
</Text>
|
||||
<Text>
|
||||
Want to add your project to Racinfo? Make a pull request on our official
|
||||
GitHub repository, and we’ll review it.
|
||||
</Text>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
@ -43,13 +43,6 @@ export default function Projects() {
|
||||
description: "Coming Soon™",
|
||||
tags: ["Unreleased", "WRAC", "RAC", "v2"],
|
||||
},
|
||||
{
|
||||
name: "oWRAC",
|
||||
authorId: "pansangg",
|
||||
projectGit: "https://github.com/pansangg/oWRAC",
|
||||
description: "An online WRAC client (works in web)",
|
||||
tags: ["Unreleased", "WRAC", "v2"],
|
||||
},
|
||||
{
|
||||
name: "clRAC",
|
||||
externalDownload: true,
|
||||
@ -116,61 +109,55 @@ export default function Projects() {
|
||||
];
|
||||
|
||||
return (
|
||||
<div className={"bg-stone-900 min-h-screen font-geist"}>
|
||||
<main
|
||||
className={"max-w-[700px] pt-15 flex flex-col gap-4 mx-auto w-full p-4"}
|
||||
>
|
||||
<NavBar />
|
||||
<PageTitle id={"projects"}>Projects</PageTitle>
|
||||
<Text>
|
||||
This is a curated list of projects that is related to RAC protocol.
|
||||
There is a client and server implementations of RAC. Note that some
|
||||
projects are not available on Git services and should be downloaded
|
||||
from external sources. They are marked with
|
||||
<InlineCode>external@</InlineCode> text at the beginning of the author
|
||||
ID. If you want to add your project to this list, please make an issue
|
||||
on our GitHub repository.
|
||||
</Text>
|
||||
<Title id={"clients"}>Clients</Title>
|
||||
<Text>
|
||||
Here is a grid of all available client for RAC protocol with their
|
||||
respective repository link.
|
||||
</Text>
|
||||
<div className={"grid grid-cols-1 md:grid-cols-2 gap-4 w-full"}>
|
||||
{clients.map((client) => (
|
||||
<ProjectCard
|
||||
key={client.name}
|
||||
name={client.name}
|
||||
externalDownload={client.externalDownload || undefined}
|
||||
externalLink={client.externalLink || undefined}
|
||||
authorId={client.authorId}
|
||||
projectGit={client.projectGit}
|
||||
description={client.description}
|
||||
tags={client.tags}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<Title id={"servers"}>Servers</Title>
|
||||
<Text>
|
||||
And here are the servers implementation! You can choose whatever you
|
||||
want and setup your own RAC server.
|
||||
</Text>
|
||||
<div className={"grid grid-cols-1 md:grid-cols-2 gap-4 w-full"}>
|
||||
{servers.map((server) => (
|
||||
<ProjectCard
|
||||
key={server.name}
|
||||
name={server.name}
|
||||
externalDownload={server.externalDownload}
|
||||
externalLink={server.externalLink}
|
||||
authorId={server.authorId}
|
||||
projectGit={server.projectGit}
|
||||
description={server.description}
|
||||
tags={server.tags}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<Footer />
|
||||
</main>
|
||||
</div>
|
||||
<main className={"flex flex-col gap-4 w-full"}>
|
||||
<PageTitle id={"projects"}>Projects</PageTitle>
|
||||
<Text>
|
||||
This is a curated list of projects that is related to RAC protocol.
|
||||
There is a client and server implementations of RAC. Note that some
|
||||
projects are not available on Git services and should be downloaded from
|
||||
external sources. They are marked with
|
||||
<InlineCode>external@</InlineCode> text at the beginning of the author
|
||||
ID. If you want to add your project to this list, please make an issue
|
||||
on our GitHub repository.
|
||||
</Text>
|
||||
<Title id={"clients"}>Clients</Title>
|
||||
<Text>
|
||||
Here is a grid of all available client for RAC protocol with their
|
||||
respective repository link.
|
||||
</Text>
|
||||
<div className={"grid grid-cols-1 md:grid-cols-2 gap-4 w-full"}>
|
||||
{clients.map((client) => (
|
||||
<ProjectCard
|
||||
key={client.name}
|
||||
name={client.name}
|
||||
externalDownload={client.externalDownload || undefined}
|
||||
externalLink={client.externalLink || undefined}
|
||||
authorId={client.authorId}
|
||||
projectGit={client.projectGit}
|
||||
description={client.description}
|
||||
tags={client.tags}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<Title id={"servers"}>Servers</Title>
|
||||
<Text>
|
||||
And here are the servers implementation! You can choose whatever you
|
||||
want and setup your own RAC server.
|
||||
</Text>
|
||||
<div className={"grid grid-cols-1 md:grid-cols-2 gap-4 w-full"}>
|
||||
{servers.map((server) => (
|
||||
<ProjectCard
|
||||
key={server.name}
|
||||
name={server.name}
|
||||
externalDownload={server.externalDownload}
|
||||
externalLink={server.externalLink}
|
||||
authorId={server.authorId}
|
||||
projectGit={server.projectGit}
|
||||
description={server.description}
|
||||
tags={server.tags}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
@ -1,81 +1,73 @@
|
||||
import NavBar from "@/components/NavBar";
|
||||
import Footer from "@/components/Footer";
|
||||
import Link from "next/link";
|
||||
import Link from "next/link";
|
||||
import Text from "@/components/blocks/Text";
|
||||
import PageTitle from "@/components/blocks/PageTitle";
|
||||
import Title from "@/components/blocks/Title";
|
||||
|
||||
export default function Protocol() {
|
||||
return (
|
||||
<div className={"bg-stone-900 min-h-screen font-geist"}>
|
||||
<main
|
||||
className={"max-w-[700px] pt-15 flex flex-col gap-4 mx-auto w-full p-4"}
|
||||
>
|
||||
<NavBar />
|
||||
<PageTitle id={"protocol"}>Protocol</PageTitle>
|
||||
<Text>
|
||||
Real Address Chat is a protocol based on TCP intended for chatting,
|
||||
like IRC. It was supposed to be an “IRC killer,” but in reality, its
|
||||
implementation is poor. There’s also a community-made successor called
|
||||
WRAC. It’s basically the same as RAC, but it uses WebSockets instead
|
||||
of TCP for connections.
|
||||
</Text>
|
||||
<Text>
|
||||
If you want to experiment with or implement RAC in your client or
|
||||
server, use the documentation below to understand how it works.
|
||||
</Text>
|
||||
<Title id={"articles"}>Articles</Title>
|
||||
<Text>Click on article down below that you want to read.</Text>
|
||||
<div className={"flex flex-col gap-2"}>
|
||||
<Link
|
||||
href={"/protocol/rac"}
|
||||
className={
|
||||
"flex flex-col bg-stone-900 border border-stone-800 p-4 transition-all duration-200 hover:border-neutral-600 hover:bg-stone-800 rounded-lg"
|
||||
}
|
||||
>
|
||||
<h1 className={"text-stone-300 font-rokkitt text-2xl font-bold"}>
|
||||
Real Address Chat Protocol
|
||||
</h1>
|
||||
<p className={"text-stone-500"}>
|
||||
This article explains the Real Address Chat protocol and how the
|
||||
client and server interact with each other using it.
|
||||
</p>
|
||||
<small className={"text-stone-600"}>Curated by @kostya-zero</small>
|
||||
</Link>
|
||||
<Link
|
||||
href={"/protocol/wrac"}
|
||||
className={
|
||||
"flex flex-col bg-stone-900 border border-stone-800 p-4 transition-all duration-200 hover:border-neutral-600 hover:bg-stone-800 rounded-lg"
|
||||
}
|
||||
>
|
||||
<h1 className={"text-stone-300 font-rokkitt text-2xl font-bold"}>
|
||||
WebSocket Real Address Chat Protocol
|
||||
</h1>
|
||||
<p className={"text-stone-500"}>
|
||||
WRAC is a WebSocket-based implementation of the RAC protocol, made
|
||||
by the community. It works the same as RAC but includes some
|
||||
additions.
|
||||
</p>
|
||||
<small className={"text-stone-600"}>Curated by @kostya-zero</small>
|
||||
</Link>
|
||||
<Link
|
||||
href={"/protocol/user-agents"}
|
||||
className={
|
||||
"flex flex-col bg-stone-900 border border-stone-800 p-4 transition-all duration-200 hover:border-neutral-600 hover:bg-stone-800 rounded-lg"
|
||||
}
|
||||
>
|
||||
<h1 className={"text-stone-300 font-rokkitt text-2xl font-bold"}>
|
||||
User Agents
|
||||
</h1>
|
||||
<p className={"text-stone-500"}>
|
||||
A community-made solution to identify clients by a unique symbol
|
||||
in front of their username.
|
||||
</p>
|
||||
<small className={"text-stone-600"}>Curated by @kostya-zero</small>
|
||||
</Link>
|
||||
</div>
|
||||
<Footer />
|
||||
</main>
|
||||
</div>
|
||||
<main className={"flex flex-col gap-4 w-full"}>
|
||||
<PageTitle id={"protocol"}>Protocol</PageTitle>
|
||||
<Text>
|
||||
Real Address Chat is a protocol based on TCP intended for chatting, like
|
||||
IRC. It was supposed to be an “IRC killer,” but in reality, its
|
||||
implementation is poor. There’s also a community-made successor called
|
||||
WRAC. It’s basically the same as RAC, but it uses WebSockets instead of
|
||||
TCP for connections.
|
||||
</Text>
|
||||
<Text>
|
||||
If you want to experiment with or implement RAC in your client or
|
||||
server, use the documentation below to understand how it works.
|
||||
</Text>
|
||||
<Title id={"articles"}>Articles</Title>
|
||||
<Text>Click on article down below that you want to read.</Text>
|
||||
<div className={"flex flex-col gap-2"}>
|
||||
<Link
|
||||
href={"/protocol/rac"}
|
||||
className={
|
||||
"flex flex-col bg-stone-900 border border-stone-800 p-4 transition-all duration-200 hover:border-neutral-600 hover:bg-stone-800 rounded-lg"
|
||||
}
|
||||
>
|
||||
<h1 className={"text-stone-300 font-rokkitt text-2xl font-bold"}>
|
||||
Real Address Chat Protocol
|
||||
</h1>
|
||||
<p className={"text-stone-500"}>
|
||||
This article explains the Real Address Chat protocol and how the
|
||||
client and server interact with each other using it.
|
||||
</p>
|
||||
<small className={"text-stone-600"}>Curated by @kostya-zero</small>
|
||||
</Link>
|
||||
<Link
|
||||
href={"/protocol/wrac"}
|
||||
className={
|
||||
"flex flex-col bg-stone-900 border border-stone-800 p-4 transition-all duration-200 hover:border-neutral-600 hover:bg-stone-800 rounded-lg"
|
||||
}
|
||||
>
|
||||
<h1 className={"text-stone-300 font-rokkitt text-2xl font-bold"}>
|
||||
WebSocket Real Address Chat Protocol
|
||||
</h1>
|
||||
<p className={"text-stone-500"}>
|
||||
WRAC is a WebSocket-based implementation of the RAC protocol, made
|
||||
by the community. It works the same as RAC but includes some
|
||||
additions.
|
||||
</p>
|
||||
<small className={"text-stone-600"}>Curated by @kostya-zero</small>
|
||||
</Link>
|
||||
<Link
|
||||
href={"/protocol/user-agents"}
|
||||
className={
|
||||
"flex flex-col bg-stone-900 border border-stone-800 p-4 transition-all duration-200 hover:border-neutral-600 hover:bg-stone-800 rounded-lg"
|
||||
}
|
||||
>
|
||||
<h1 className={"text-stone-300 font-rokkitt text-2xl font-bold"}>
|
||||
User Agents
|
||||
</h1>
|
||||
<p className={"text-stone-500"}>
|
||||
A community-made solution to identify clients by a unique symbol in
|
||||
front of their username.
|
||||
</p>
|
||||
<small className={"text-stone-600"}>Curated by @kostya-zero</small>
|
||||
</Link>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
import NavBar from "@/components/NavBar";
|
||||
import Footer from "@/components/Footer";
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import {
|
||||
Table,
|
||||
@ -18,189 +16,179 @@ import Code from "@/components/blocks/Code";
|
||||
|
||||
export default function Rac() {
|
||||
return (
|
||||
<div className={"bg-stone-900 min-h-screen font-geist"}>
|
||||
<main
|
||||
className={"max-w-[700px] pt-15 flex flex-col gap-4 mx-auto w-full p-4"}
|
||||
<main className={"flex flex-col gap-4 w-full"}>
|
||||
<Link
|
||||
href={"/protocol"}
|
||||
className={
|
||||
"text-stone-500 flex flex-row items-center transition duration-200 hover:text-stone-50 gap-2"
|
||||
}
|
||||
>
|
||||
<NavBar />
|
||||
<Link
|
||||
href={"/protocol"}
|
||||
className={
|
||||
"text-stone-500 flex flex-row items-center transition duration-200 hover:text-stone-50 gap-2"
|
||||
}
|
||||
>
|
||||
<ArrowLeft size={16} /> Go Back
|
||||
</Link>
|
||||
<PageTitle id={"real-address-chat-protocol"}>
|
||||
Real Address Chat Protocol
|
||||
</PageTitle>
|
||||
<Text>
|
||||
As mentioned earlier, RAC is a TCP-based protocol, so the server and
|
||||
client communicate by sending TCP packets to each other. The
|
||||
implementation is pretty simple, so don’t worry.
|
||||
</Text>
|
||||
<Text>
|
||||
All RAC servers use port <InlineCode>42666</InlineCode> by default,
|
||||
but servers that implement RACS (Real Address Chat Secure) use port{" "}
|
||||
<InlineCode>42667</InlineCode>.
|
||||
</Text>
|
||||
<Text>
|
||||
Keep in mind that the RAC server closes the connection after each
|
||||
message sent from the client. In some cases, it might receive two
|
||||
packets, but it will still close the connection.
|
||||
</Text>
|
||||
<Title id={"receiving-messages"}>Receiving messages</Title>
|
||||
<Text>
|
||||
Receiving messages from the server is implemented in an unusual way.
|
||||
There are two ways to receive messages from the server.
|
||||
</Text>
|
||||
<Text>
|
||||
But before you try to receive new messages, you need to get the total
|
||||
size of all messages. The messages are stored on the server in a
|
||||
single file, and to get new messages, you should send an offset.
|
||||
</Text>
|
||||
<Text>
|
||||
To receive the current size of the messages on the server, you need to
|
||||
send a <InlineCode>0x00</InlineCode> byte to the server. In response,
|
||||
the server will return the current size of the messages. Now, let’s
|
||||
begin receiving those messages.
|
||||
</Text>
|
||||
<Text>
|
||||
The first way is to receive all messages stored on the server. The
|
||||
client should send a <InlineCode>0x00</InlineCode> byte and then, in
|
||||
the same stream, send a <InlineCode>0x01</InlineCode> byte to the
|
||||
server. The server will respond with all messages, separated by{" "}
|
||||
<InlineCode>\n</InlineCode>.
|
||||
</Text>
|
||||
<Text>
|
||||
The second way is to get messages in chunks. Again, the client sends a{" "}
|
||||
<InlineCode>0x00</InlineCode> byte and then sends a{" "}
|
||||
<InlineCode>0x02</InlineCode> byte, along with the size of the
|
||||
messages it wants to receive. The number of messages to receive is
|
||||
calculated using this formula:
|
||||
</Text>
|
||||
<Code>new_received_size - last_known_size</Code>
|
||||
<Text>
|
||||
The server will send messages matching the requested size, separated
|
||||
by <InlineCode>\n</InlineCode>.
|
||||
</Text>
|
||||
<Title id={"sending-messages"}>Sending messages</Title>
|
||||
<Text>
|
||||
Sending messages in RAC is implemented simply, but with some
|
||||
interesting details. The server doesn’t identify clients or users, so
|
||||
clients have to handle that themselves. This means the client must
|
||||
send the user agent, username, and message all in one packet. For
|
||||
example:
|
||||
</Text>
|
||||
<Code>{"▲<zero> Hello, world!"}</Code>
|
||||
<Text>
|
||||
Did you notice the <InlineCode>▲</InlineCode> symbol? This is called a
|
||||
User Agent. In this example, the message was sent by the Tower client,
|
||||
because <InlineCode>▲</InlineCode> is its respective user agent. As
|
||||
mentioned earlier, the server itself cannot identify clients, so
|
||||
clients have to identify each other using these user agents.
|
||||
</Text>
|
||||
<Text>
|
||||
Also, note that <InlineCode>zero</InlineCode> is wrapped inside{" "}
|
||||
<InlineCode>{"<>"}</InlineCode>. This approach makes parsing messages
|
||||
easier with regex. Learn more about user agents and how to create your
|
||||
own in the user agents article.
|
||||
</Text>
|
||||
<Text>
|
||||
Note that the server should store the IP address with each sent
|
||||
message. However, messages sent by clients in authorized mode should
|
||||
be ignored for this. This idea, introduced by Sugoma, means that
|
||||
clients shouldn’t be anonymous unless they’re authorized. Still, most
|
||||
clients ignore the IP address and don’t display it.
|
||||
</Text>
|
||||
<Text>
|
||||
Back to sending messages: To send a message to the server, the client
|
||||
should send a <InlineCode>0x01</InlineCode> byte, followed by the
|
||||
message in the same packet—not separately. After that, you won’t
|
||||
receive anything from the server, even if there’s an error. So your
|
||||
final message should look like this:
|
||||
</Text>
|
||||
<Code>{"<user> Hello, everyone!"}</Code>
|
||||
<Text>
|
||||
Also, server that are implements RAC v2 allows to send messages in
|
||||
authorized mode. To send message in authorized mode, you need to send{" "}
|
||||
<InlineCode>0x02</InlineCode> and after that, separating by{" "}
|
||||
<InlineCode>\n</InlineCode>, send user's user name, password and
|
||||
message (<b>do not</b> include <InlineCode>\n</InlineCode> in the
|
||||
end).
|
||||
</Text>
|
||||
<Text>
|
||||
If the message was sent successfully, the server won’t send any
|
||||
response. If not, the server will send a <InlineCode>0x01</InlineCode>{" "}
|
||||
byte if the user doesn’t exist, and a <InlineCode>0x02</InlineCode>{" "}
|
||||
byte if the password is incorrect.
|
||||
</Text>
|
||||
<Title id={"authorization"}>Authorization</Title>
|
||||
<Text>
|
||||
Authorization is only available on servers that implement the RAC v2
|
||||
protocol, which adds an authorization system. This feature was added
|
||||
by Sugoma for people who don’t want to expose their IP address to
|
||||
everyone.
|
||||
</Text>
|
||||
<Text>
|
||||
Before sending messages in authorized mode, you need to register a
|
||||
user on the server. To do this, the client should send a{" "}
|
||||
<InlineCode>0x03</InlineCode> byte and, just like when sending
|
||||
messages, include the username and password separated by{" "}
|
||||
<InlineCode>\n</InlineCode>. If the user is created, the client will
|
||||
receive nothing in response. If the user already exists, the server
|
||||
will respond with a <InlineCode>0x01</InlineCode> byte.
|
||||
</Text>
|
||||
<Title id={"tls-connection"}>TLS Connection</Title>
|
||||
<Text>
|
||||
You can wrap your connection with TLS encryption. There’s nothing
|
||||
special about it.
|
||||
</Text>
|
||||
<Title id={"special-packets"}>Special Packets</Title>
|
||||
<Text>
|
||||
Some servers can implement special packets, but most of the time they
|
||||
don’t add much functionality.
|
||||
</Text>
|
||||
<Text>
|
||||
One of them is the <InlineCode>0x69</InlineCode> byte. You can send
|
||||
this byte to the server to get technical information about it. For
|
||||
example, after sending this byte, you might receive these bytes in
|
||||
response:
|
||||
</Text>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className={"w-[150px]"}>Byte</TableHead>
|
||||
<TableHead>Meaning</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell className={"font-semibold"}>
|
||||
<InlineCode>0x01</InlineCode>
|
||||
</TableCell>
|
||||
<TableCell>The server supports RAC v1.0</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell className={"font-semibold"}>
|
||||
<InlineCode>0x02</InlineCode>
|
||||
</TableCell>
|
||||
<TableCell>The server supports RAC v1.99</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell className={"font-semibold"}>
|
||||
<InlineCode>0x03</InlineCode>
|
||||
</TableCell>
|
||||
<TableCell>The server supports RAC v2.0</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
<Text>
|
||||
Also, right after this byte, the server will send information about
|
||||
itself, such as the server software name and its version.
|
||||
</Text>
|
||||
<Footer />
|
||||
</main>
|
||||
</div>
|
||||
<ArrowLeft size={16} /> Go Back
|
||||
</Link>
|
||||
<PageTitle id={"real-address-chat-protocol"}>
|
||||
Real Address Chat Protocol
|
||||
</PageTitle>
|
||||
<Text>
|
||||
As mentioned earlier, RAC is a TCP-based protocol, so the server and
|
||||
client communicate by sending TCP packets to each other. The
|
||||
implementation is pretty simple, so don’t worry.
|
||||
</Text>
|
||||
<Text>
|
||||
All RAC servers use port <InlineCode>42666</InlineCode> by default, but
|
||||
servers that implement RACS (Real Address Chat Secure) use port{" "}
|
||||
<InlineCode>42667</InlineCode>.
|
||||
</Text>
|
||||
<Text>
|
||||
Keep in mind that the RAC server closes the connection after each
|
||||
message sent from the client. In some cases, it might receive two
|
||||
packets, but it will still close the connection.
|
||||
</Text>
|
||||
<Title id={"receiving-messages"}>Receiving messages</Title>
|
||||
<Text>
|
||||
Receiving messages from the server is implemented in an unusual way.
|
||||
There are two ways to receive messages from the server.
|
||||
</Text>
|
||||
<Text>
|
||||
But before you try to receive new messages, you need to get the total
|
||||
size of all messages. The messages are stored on the server in a single
|
||||
file, and to get new messages, you should send an offset.
|
||||
</Text>
|
||||
<Text>
|
||||
To receive the current size of the messages on the server, you need to
|
||||
send a <InlineCode>0x00</InlineCode> byte to the server. In response,
|
||||
the server will return the current size of the messages. Now, let’s
|
||||
begin receiving those messages.
|
||||
</Text>
|
||||
<Text>
|
||||
The first way is to receive all messages stored on the server. The
|
||||
client should send a <InlineCode>0x00</InlineCode> byte and then, in the
|
||||
same stream, send a <InlineCode>0x01</InlineCode> byte to the server.
|
||||
The server will respond with all messages, separated by{" "}
|
||||
<InlineCode>\n</InlineCode>.
|
||||
</Text>
|
||||
<Text>
|
||||
The second way is to get messages in chunks. Again, the client sends a{" "}
|
||||
<InlineCode>0x00</InlineCode> byte and then sends a{" "}
|
||||
<InlineCode>0x02</InlineCode> byte, along with the size of the messages
|
||||
it wants to receive. The number of messages to receive is calculated
|
||||
using this formula:
|
||||
</Text>
|
||||
<Code>new_received_size - last_known_size</Code>
|
||||
<Text>
|
||||
The server will send messages matching the requested size, separated by{" "}
|
||||
<InlineCode>\n</InlineCode>.
|
||||
</Text>
|
||||
<Title id={"sending-messages"}>Sending messages</Title>
|
||||
<Text>
|
||||
Sending messages in RAC is implemented simply, but with some interesting
|
||||
details. The server doesn’t identify clients or users, so clients have
|
||||
to handle that themselves. This means the client must send the user
|
||||
agent, username, and message all in one packet. For example:
|
||||
</Text>
|
||||
<Code>{"▲<zero> Hello, world!"}</Code>
|
||||
<Text>
|
||||
Did you notice the <InlineCode>▲</InlineCode> symbol? This is called a
|
||||
User Agent. In this example, the message was sent by the Tower client,
|
||||
because <InlineCode>▲</InlineCode> is its respective user agent. As
|
||||
mentioned earlier, the server itself cannot identify clients, so clients
|
||||
have to identify each other using these user agents.
|
||||
</Text>
|
||||
<Text>
|
||||
Also, note that <InlineCode>zero</InlineCode> is wrapped inside{" "}
|
||||
<InlineCode>{"<>"}</InlineCode>. This approach makes parsing messages
|
||||
easier with regex. Learn more about user agents and how to create your
|
||||
own in the user agents article.
|
||||
</Text>
|
||||
<Text>
|
||||
Note that the server should store the IP address with each sent message.
|
||||
However, messages sent by clients in authorized mode should be ignored
|
||||
for this. This idea, introduced by Sugoma, means that clients shouldn’t
|
||||
be anonymous unless they’re authorized. Still, most clients ignore the
|
||||
IP address and don’t display it.
|
||||
</Text>
|
||||
<Text>
|
||||
Back to sending messages: To send a message to the server, the client
|
||||
should send a <InlineCode>0x01</InlineCode> byte, followed by the
|
||||
message in the same packet—not separately. After that, you won’t receive
|
||||
anything from the server, even if there’s an error. So your final
|
||||
message should look like this:
|
||||
</Text>
|
||||
<Code>{"<user> Hello, everyone!"}</Code>
|
||||
<Text>
|
||||
Also, server that are implements RAC v2 allows to send messages in
|
||||
authorized mode. To send message in authorized mode, you need to send{" "}
|
||||
<InlineCode>0x02</InlineCode> and after that, separating by{" "}
|
||||
<InlineCode>\n</InlineCode>, send user's user name, password and
|
||||
message (<b>do not</b> include <InlineCode>\n</InlineCode> in the end).
|
||||
</Text>
|
||||
<Text>
|
||||
If the message was sent successfully, the server won’t send any
|
||||
response. If not, the server will send a <InlineCode>0x01</InlineCode>{" "}
|
||||
byte if the user doesn’t exist, and a <InlineCode>0x02</InlineCode> byte
|
||||
if the password is incorrect.
|
||||
</Text>
|
||||
<Title id={"authorization"}>Authorization</Title>
|
||||
<Text>
|
||||
Authorization is only available on servers that implement the RAC v2
|
||||
protocol, which adds an authorization system. This feature was added by
|
||||
Sugoma for people who don’t want to expose their IP address to everyone.
|
||||
</Text>
|
||||
<Text>
|
||||
Before sending messages in authorized mode, you need to register a user
|
||||
on the server. To do this, the client should send a{" "}
|
||||
<InlineCode>0x03</InlineCode> byte and, just like when sending messages,
|
||||
include the username and password separated by{" "}
|
||||
<InlineCode>\n</InlineCode>. If the user is created, the client will
|
||||
receive nothing in response. If the user already exists, the server will
|
||||
respond with a <InlineCode>0x01</InlineCode> byte.
|
||||
</Text>
|
||||
<Title id={"tls-connection"}>TLS Connection</Title>
|
||||
<Text>
|
||||
You can wrap your connection with TLS encryption. There’s nothing
|
||||
special about it.
|
||||
</Text>
|
||||
<Title id={"special-packets"}>Special Packets</Title>
|
||||
<Text>
|
||||
Some servers can implement special packets, but most of the time they
|
||||
don’t add much functionality.
|
||||
</Text>
|
||||
<Text>
|
||||
One of them is the <InlineCode>0x69</InlineCode> byte. You can send this
|
||||
byte to the server to get technical information about it. For example,
|
||||
after sending this byte, you might receive these bytes in response:
|
||||
</Text>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className={"w-[150px]"}>Byte</TableHead>
|
||||
<TableHead>Meaning</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell className={"font-semibold"}>
|
||||
<InlineCode>0x01</InlineCode>
|
||||
</TableCell>
|
||||
<TableCell>The server supports RAC v1.0</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell className={"font-semibold"}>
|
||||
<InlineCode>0x02</InlineCode>
|
||||
</TableCell>
|
||||
<TableCell>The server supports RAC v1.99</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell className={"font-semibold"}>
|
||||
<InlineCode>0x03</InlineCode>
|
||||
</TableCell>
|
||||
<TableCell>The server supports RAC v2.0</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
<Text>
|
||||
Also, right after this byte, the server will send information about
|
||||
itself, such as the server software name and its version.
|
||||
</Text>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
import NavBar from "@/components/NavBar";
|
||||
import Footer from "@/components/Footer";
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import {
|
||||
Table,
|
||||
@ -60,69 +58,61 @@ export default function Wrac() {
|
||||
},
|
||||
];
|
||||
return (
|
||||
<div className={"bg-stone-900 min-h-screen font-geist"}>
|
||||
<main
|
||||
className={"max-w-[700px] pt-15 flex flex-col gap-4 mx-auto w-full p-4"}
|
||||
<main className={"flex flex-col gap-4 w-full"}>
|
||||
<Link
|
||||
href={"/protocol"}
|
||||
className={
|
||||
"text-stone-500 flex flex-row items-center transition duration-200 hover:text-stone-50 gap-2"
|
||||
}
|
||||
>
|
||||
<NavBar />
|
||||
<Link
|
||||
href={"/protocol"}
|
||||
className={
|
||||
"text-stone-500 flex flex-row items-center transition duration-200 hover:text-stone-50 gap-2"
|
||||
}
|
||||
>
|
||||
<ArrowLeft size={16} /> Go Back
|
||||
</Link>
|
||||
<PageTitle id={"user-agents"}>User Agents</PageTitle>
|
||||
<Text>
|
||||
The RAC protocol doesn’t have any functionality to identify clients,
|
||||
so the community decided to use their own solution called{" "}
|
||||
<b>User Agents</b>.
|
||||
</Text>
|
||||
<Text>
|
||||
User Agents in RAC are implemented by adding an extra Unicode symbol
|
||||
as a prefix to usernames. For example, a message sent with the Tower
|
||||
client:
|
||||
</Text>
|
||||
<Code>{"▲<zero> Hello, world!"}</Code>
|
||||
<Text>
|
||||
The <InlineCode>▲</InlineCode> symbol in front of the username
|
||||
indicates that this message was sent using the Tower client. The
|
||||
client should use regex to parse these messages and determine the
|
||||
client, username, and message.
|
||||
</Text>
|
||||
<h3 className={"text-3xl text-stone-300 font-semibold font-rokkitt"}>
|
||||
Known Agents
|
||||
</h3>
|
||||
<Text>
|
||||
Below is a table of known user agents with their client names and
|
||||
regular expressions. Clients can also optionally use colored usernames
|
||||
for each client. You can add your own user agent via a pull request.
|
||||
</Text>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className={"w-[150px]"}>Client Name</TableHead>
|
||||
<TableHead>Regular Expression</TableHead>
|
||||
<TableHead>Color</TableHead>
|
||||
<ArrowLeft size={16} /> Go Back
|
||||
</Link>
|
||||
<PageTitle id={"user-agents"}>User Agents</PageTitle>
|
||||
<Text>
|
||||
The RAC protocol doesn’t have any functionality to identify clients, so
|
||||
the community decided to use their own solution called{" "}
|
||||
<b>User Agents</b>.
|
||||
</Text>
|
||||
<Text>
|
||||
User Agents in RAC are implemented by adding an extra Unicode symbol as
|
||||
a prefix to usernames. For example, a message sent with the Tower
|
||||
client:
|
||||
</Text>
|
||||
<Code>{"▲<zero> Hello, world!"}</Code>
|
||||
<Text>
|
||||
The <InlineCode>▲</InlineCode> symbol in front of the username indicates
|
||||
that this message was sent using the Tower client. The client should use
|
||||
regex to parse these messages and determine the client, username, and
|
||||
message.
|
||||
</Text>
|
||||
<h3 className={"text-3xl text-stone-300 font-semibold font-rokkitt"}>
|
||||
Known Agents
|
||||
</h3>
|
||||
<Text>
|
||||
Below is a table of known user agents with their client names and
|
||||
regular expressions. Clients can also optionally use colored usernames
|
||||
for each client. You can add your own user agent via a pull request.
|
||||
</Text>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className={"w-[150px]"}>Client Name</TableHead>
|
||||
<TableHead>Regular Expression</TableHead>
|
||||
<TableHead>Color</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{userAgents.map((agent) => (
|
||||
<TableRow key={agent.client}>
|
||||
<TableCell className={"font-semibold"}>{agent.client}</TableCell>
|
||||
<TableCell>
|
||||
<code>{agent.regex}</code>
|
||||
</TableCell>
|
||||
<TableCell>{agent.color}</TableCell>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{userAgents.map((agent) => (
|
||||
<TableRow key={agent.client}>
|
||||
<TableCell className={"font-semibold"}>
|
||||
{agent.client}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<code>{agent.regex}</code>
|
||||
</TableCell>
|
||||
<TableCell>{agent.color}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<Footer />
|
||||
</main>
|
||||
</div>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
import NavBar from "@/components/NavBar";
|
||||
import Footer from "@/components/Footer";
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import Text from "@/components/blocks/Text";
|
||||
import PageTitle from "@/components/blocks/PageTitle";
|
||||
@ -9,45 +7,37 @@ import InlineCode from "@/components/blocks/InlineCode";
|
||||
|
||||
export default function Wrac() {
|
||||
return (
|
||||
<div className={"bg-stone-900 min-h-screen font-geist"}>
|
||||
<main
|
||||
className={"max-w-[700px] pt-15 flex flex-col gap-4 mx-auto w-full p-4"}
|
||||
<main className={"flex flex-col gap-4 w-full"}>
|
||||
<Link
|
||||
href={"/protocol"}
|
||||
className={
|
||||
"text-stone-500 flex flex-row items-center transition duration-200 hover:text-stone-50 gap-2"
|
||||
}
|
||||
>
|
||||
<NavBar />
|
||||
<Link
|
||||
href={"/protocol"}
|
||||
className={
|
||||
"text-stone-500 flex flex-row items-center transition duration-200 hover:text-stone-50 gap-2"
|
||||
}
|
||||
>
|
||||
<ArrowLeft size={16} /> Go Back
|
||||
</Link>
|
||||
<PageTitle id={"websocket-real-address-chat-protocol"}>
|
||||
WebSocket Real Address Chat Protocol
|
||||
</PageTitle>
|
||||
<Text>
|
||||
WRAC (WebSocket Real Address Chat) is a community-made successor to
|
||||
RAC that uses WebSockets instead of TCP. It uses the same requests as
|
||||
RAC, but you should send data in binary format. Unlike regular RAC,
|
||||
you can use the same connection multiple times—in RAC, you had to
|
||||
reconnect to the server for every request. This changes how message
|
||||
receiving works.
|
||||
</Text>
|
||||
<Title id={"receiving-messages"}>Receiving messages</Title>
|
||||
<Text>
|
||||
Since the connection can now be kept alive and WebSocket uses messages
|
||||
for transactions, we can’t retrieve messages the same way as in RAC.
|
||||
</Text>
|
||||
<Text>
|
||||
Receiving messages in WRAC is done by sending a single packet to the
|
||||
server with two bytes. The first byte is <InlineCode>0x00</InlineCode>
|
||||
, which indicates that you want to receive messages, and the second
|
||||
byte is either <InlineCode>0x01</InlineCode> or{" "}
|
||||
<InlineCode>0x02</InlineCode>. These two bytes work the same way as in
|
||||
RAC.
|
||||
</Text>
|
||||
<Footer />
|
||||
</main>
|
||||
</div>
|
||||
<ArrowLeft size={16} /> Go Back
|
||||
</Link>
|
||||
<PageTitle id={"websocket-real-address-chat-protocol"}>
|
||||
WebSocket Real Address Chat Protocol
|
||||
</PageTitle>
|
||||
<Text>
|
||||
WRAC (WebSocket Real Address Chat) is a community-made successor to RAC
|
||||
that uses WebSockets instead of TCP. It uses the same requests as RAC,
|
||||
but you should send data in binary format. Unlike regular RAC, you can
|
||||
use the same connection multiple times—in RAC, you had to reconnect to
|
||||
the server for every request. This changes how message receiving works.
|
||||
</Text>
|
||||
<Title id={"receiving-messages"}>Receiving messages</Title>
|
||||
<Text>
|
||||
Since the connection can now be kept alive and WebSocket uses messages
|
||||
for transactions, we can’t retrieve messages the same way as in RAC.
|
||||
</Text>
|
||||
<Text>
|
||||
Receiving messages in WRAC is done by sending a single packet to the
|
||||
server with two bytes. The first byte is <InlineCode>0x00</InlineCode>,
|
||||
which indicates that you want to receive messages, and the second byte
|
||||
is either <InlineCode>0x01</InlineCode> or <InlineCode>0x02</InlineCode>
|
||||
. These two bytes work the same way as in RAC.
|
||||
</Text>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user