Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
DrewML committed Dec 12, 2020
0 parents commit c2d4113
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
npm-debug.log
dist
node_modules
.DS_Store
5 changes: 5 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dist
generated
.vscode
package-lock.json
package.json
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# AOL Instant Messenger Server

This is a (very wip) server-side implementation of the [Oscar Protocol](https://en.wikipedia.org/wiki/OSCAR_protocol), used by [AOL Instant Messenger](<https://en.wikipedia.org/wiki/AIM_(software)>) and later versions of [ICQ](https://en.wikipedia.org/wiki/ICQ).

## Working

- AIM Client can establish connection and server can send and receive the FLAP SIGNON frame
- Can receive initial auth flap from client

## Oscar Protocol Resources

- http://web.archive.org/web/20080308233204/http://dev.aol.com/aim/oscar/ (AOL published Oscar protocol documentation in the mid 00s)
- http://iserverd.khstu.ru/oscar/ (Unofficial protocol docs, pretty thorough)
- https://wiki.nina.bz/wiki/Protocols/OSCAR (From the Nina group also working on an OSCAR server)
- https://github.com/bitm4ster/AOL-Instant-Messenger-Server/ (Oscar server written in VB6. and it actually compiles!)
- http://iserverd.khstu.ru/download/ (Oscar Server written in C++. Haven't attempted to compile yet, but a great reference)
26 changes: 26 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "aim-server",
"private": true,
"version": "0.0.1",
"description": "An AOL Instant Messenger Server. Implements a subset of the Oscar Protocol",
"main": "index.js",
"scripts": {
"build": "tsc",
"watch": "tsc --watch",
"format:check": "prettier --list-different '**/*.{js,ts,md,json}'",
"format": "prettier --write '**/*.{js,ts,md,json}'"
},
"author": "Andrew Levine",
"license": "MIT",
"devDependencies": {
"@types/node": "^14.14.11",
"prettier": "^2.2.1",
"typescript": "^4.1.2"
}
}
5 changes: 5 additions & 0 deletions prettier.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
singleQuote: true,
tabWidth: 4,
trailingComma: 'all',
};
97 changes: 97 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import net from 'net';
import assert from 'assert';

interface Flap {
channel: number;
sequence: number;
byteLength: number;
data: Buffer;
}

/**
* @see https://en.wikipedia.org/wiki/OSCAR_protocol#FLAP_header
*/
function parseFlap(msg: Buffer): Flap {
const id = msg.readUInt8(0);
assert(id === 0x2a, 'Unexpected Flap ID');

return {
channel: msg.readUInt8(1),
sequence: msg.readUInt16BE(2),
byteLength: msg.readUInt16BE(4),
data: Buffer.from(msg, 6),
};
}

/**
* @see http://web.archive.org/web/20080308233204/http://dev.aol.com/aim/oscar/#FLAP__SIGNON_FRAME
*/
function signonFlap() {
const buf = Buffer.alloc(7);
buf.writeUInt8(0x2a, 0); // start byte
buf.writeUInt8(0x1, 1); // flap channel
buf.writeUInt16BE(0x1, 2); // sequence number
buf.writeUInt16BE(0x1, 4); // data size (flap version)
buf.writeUInt8(0x1, 6); // flap version

return buf;
}

const server = net.createServer((c) => {
console.log('New socket opened');

c.on('end', () => {
console.log('client disconnected');
});

c.on('connect', () => console.log('Socket connected'));
c.on('error', (e) => console.log('Socket error', e));
c.on('close', () => {
console.log('socket closed');
});

function onChannel2Message(flap: Flap) {
console.log('Channel 2 Flap: ', flap);
}

c.on('data', (buf) => {
const flap = parseFlap(buf);
// http://web.archive.org/web/20080308233204/http://dev.aol.com/aim/oscar/#FLAP__FRAME_TYPE
switch (flap.channel) {
case 1:
// SIGNON frame response
// TODO: assert flap version is always 1
break;
case 2:
onChannel2Message(flap);
break;
case 3:
// FLAP-level error
// TODO: Error logging
break;
case 4:
// Signoff negotiation
// TODO: Implement when sessions are implemented
break;
case 5:
// Keep-alive heartbeat
// TODO: Implement when sessions are implemented
break;
default:
throw new Error(`Unrecognized FLAP channel "${flap.channel}"`);
}
});

// Send OSCAR connection handshake
c.write(signonFlap());
});

server.on('error', (err) => {
console.error('Server crashed. Welp');
console.error(err);
process.exit(1);
});

server.listen(5190, () => {
console.log('Oscar Auth Server listening on 5190');
});
17 changes: 17 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"inlineSourceMap": true,
"inlineSources": true,
"strict": true,
"target": "ES2020",
"module": "commonjs",
"moduleResolution": "node",
"esModuleInterop": true,
"outDir": "dist",
"noImplicitAny": true,
"noEmitOnError": false,
"resolveJsonModule": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "**/__tests__/**"]
}

0 comments on commit c2d4113

Please sign in to comment.