Blue IRC Server
by BlueOwl
; copyright BlueOwl (2005)
include '%fasminc%/win32ax.inc'
; ************* EQUALS ***********************************************
pass_start equ "test"
pass_end equ "pass"
max_connections equ 500
max_wait_connection equ 40000
max_bans equ 100
bind_port equ 6667
FIONBIO equ 8004667Eh
WSAEWOULDBLOCK equ 10035
WSAENOTSOCK equ 10038
.data
; ************* SERVER DATA ******************************************
nonblocking dd ?
msock dd ?
master dd ? ; socket of oper
maddr sockaddr_in
sbuffer rb 1024
_wsadata WSADATA
; ************* CLIENT DATA ******************************************
rsock dd ?
rsize dd ?
raddr_size dd ?
rnick rb 16
rip rb 64
ripaddr rb 12
raddr sockaddr_in
rbuffer rb 1024
clients rb 20*max_connections
.code
; ************* STARTUP **********************************************
start: ret ; -- be sure you know what you do with this.
mov [nonblocking], 1
mov [raddr_size], sockaddr_in
invoke WSAStartup,0101h,_wsadata
or eax, eax
jnz exit_startup
invoke socket,AF_INET,SOCK_STREAM,0
cmp eax, -1
jz do_cleanup
mov [msock], eax
invoke ioctlsocket,[msock],FIONBIO,nonblocking
mov ax, bind_port
xchg al, ah
mov [maddr.sin_port],ax
mov [maddr.sin_addr],0
mov [maddr.sin_family],AF_INET
invoke bind,[msock],maddr,sizeof.sockaddr
invoke listen,[msock],1
; ############# WAIT FOR CONNECTION LOOP #############################
; ************* CHECK FOR NEW CONNECTION *****************************
server_loop: invoke accept,[msock],raddr,raddr_size
mov [rsock], eax
invoke WSAGetLastError
cmp eax, WSAEWOULDBLOCK
jz connection_okay
or eax, eax
jnz close_msock
stdcall send_data,[rsock],lookup_host,0,0
invoke GetTickCount
add eax, max_wait_connection
mov dword [ripaddr], eax
stdcall add_session,ripaddr,[raddr.sin_addr],[rsock]
; ************* PROCESS CURRENT CONNECTIONS **************************
connection_okay:mov esi, clients
mov ecx, max_connections
next_connection:push esi ecx
cmp dword [esi], 0
jz connection_done
invoke recv,dword [esi+16],rbuffer,1024,0
mov [rsize], eax
or eax, eax
jz do_close
invoke WSAGetLastError
cmp eax, WSAENOTSOCK
jnz connection_open
mov eax, dword [esi+16]
do_close: cmp dword [master], eax
jnz not_master
and dword [master], 0
not_master: invoke closesocket,dword [esi+16]
stdcall send_data,[master],quit_msg,esi,0
mov edi, esi
mov ecx, 5
sub eax, eax
rep stosd
jmp connection_done
connection_open:cmp eax, WSAEWOULDBLOCK
jz connection_done
cmp [rsize], 1024
ja do_close
call process_command
connection_done:pop ecx esi
add esi, 20
dec ecx
jnz next_connection
; ************* PROCESS UNKNOWN CONNECTIONS *************************
invoke GetTickCount
mov esi, clients
mov ecx, max_connections
unknown_connection_loop:
push ecx esi eax
cmp dword [esi], 0
jz skip_unknown_connection
cmp byte [esi+4], 0
jnz skip_unknown_connection
cmp dword [esi], eax
ja skip_unknown_connection
invoke closesocket,dword [esi+16]
skip_unknown_connection:
pop eax esi ecx
add esi, 20
loop unknown_connection_loop
invoke Sleep, 1000
jmp server_loop
; ************* EXIT PROGRAM *****************************************
close_msock: invoke closesocket,[msock]
do_cleanup: invoke WSACleanup
exit_startup: invoke ExitProcess,0
; ############# PROCESS COMMAND FUNCTION ############################
process_command:xchg esi, edx
mov esi, rbuffer
sub eax, eax
endzero_command:inc eax
cmp byte [esi+eax], 13
jz zero_command
cmp byte [esi+eax], 10
jnz endzero_command
zero_command: mov byte [esi+eax], 0
lodsd
or eax, 020202020h
cmp eax, "oper"
jz process_oper
cmp eax, "nick"
jz process_nick
mov eax, [edx+16]
cmp [master], eax
jz is_master
cmp dword [master], 0
jz skip_clientmsg
mov eax, [esi-4]
or eax, 20202020h
cmp eax, "priv"
jz process_privmsg_client
skip_clientmsg: ret
; ************* PROCESS OPER ****************************************
process_oper: lodsb
cmp al, " "
jnz opernogood
lodsd
cmp eax, pass_start
jnz opernogood
lodsd
cmp eax, pass_end
jz operrecognized
opernogood: ret
operrecognized: mov eax, [edx+16]
mov [master], eax
stdcall send_data,[master],oper_msg,edx,0
mov esi, clients
mov ecx, max_connections
show_clients_oper:push esi ecx
cmp dword [esi], 0
jz skip_client_oper
mov eax, [master]
cmp dword [esi+16], eax
jz skip_client_oper ; do not show the oper self
cmp byte [esi+4], 0
jz skip_client_oper ; don't show pending connections
xchg eax, esi
call convert_to_ip
stdcall send_data,[master],join_msg,rip,0
skip_client_oper:pop ecx esi
add esi, 20
loop show_clients_oper
ret
; ************* PROCESS NICK ****************************************
process_nick: lodsb
cmp al, " "
jnz nick_invalid
stdcall find_session,esi
or eax, eax
jnz nick_invalid
sub ecx, ecx
dec ecx
sizenick: inc ecx
cmp byte [esi+ecx], 0
jnz sizenick
and dword [esi+ecx], 0
and dword [esi+ecx+4], 0
and dword [esi+ecx+8], 0
cmp ecx, 4
jb nick_invalid
cmp ecx, 12
jae nick_invalid
mov edi, clients
mov ecx, max_connections
mov eax, [edx+16]
do_find_connection:
cmp dword [edi+16], eax
jz connection_found
add edi, 20
loop do_find_connection
invoke closesocket,eax ; weird shit happening
ret
connection_found:
push edi
movsd
movsd
movsd
pop edi
stdcall send_data,dword [edi+16],welcome_msg,edi,0
xchg eax, edi
call convert_to_ip
stdcall send_data,[master],join_msg,rip,0
nick_invalid: ret
; ************* COMMAND FROM MASTER *********************************
is_master: mov eax, [esi-4]
or eax, 020202020h
cmp eax, "priv"
jz process_privmsg_master
cmp eax, "kill"
jz process_kill
cmp eax, "whoi"
jz process_whois
mov ax, [esi-4]
or ax, 02020h
cmp ax, "di"
jz process_die
ret
; ************* PROCESS PRIVMSG FROM MASTER *************************
process_privmsg_master:
lodsd
or eax, 020202020h
cmp eax, "msg "
jz privmsg_master_ok
ret
privmsg_master_ok:
cmp byte [esi], "#"
jz privmsg_master_channel
mov edi, rnick
push edi
sub eax, eax
mov ecx, 5
rep stosd
pop edi
copy_msgnick: movsb
cmp byte [esi], " "
jnz copy_msgnick
add esi, 2
stdcall find_session,rnick
stdcall send_data,dword [eax+16],server_privmsg,rnick,esi
ret
privmsg_master_channel:
lodsb
cmp al, ":"
jnz privmsg_master_channel
mov edi, clients
mov ecx, max_connections
msg_clients_channel:
push edi ecx
cmp dword [edi], 0
jz skip_msgclient
mov eax, [master]
cmp dword [edi+16], eax
jz skip_msgclient
stdcall send_data,dword [edi+16],master_channel_privmsg,esi,0
skip_msgclient: pop ecx edi
add edi, 20
loop msg_clients_channel
ret
; ************* PROCESS WHOIS FROM MASTER ***************************
process_whois: add esi, 2
stdcall find_session,esi
or eax, eax
jnz whois_ok
ret
whois_ok: call convert_to_ip
stdcall send_data,[master],whois_msg,esi,rip
ret
; ************* PROCESS DIE FROM MASTER *****************************
process_die: mov esi, clients
mov ecx, max_connections
close_connections:
push esi ecx
invoke closesocket,dword [esi+16]
pop ecx esi
add esi, 20
loop close_connections
jmp close_msock
; ************* PROCESS KILL FROM MASTER ****************************
process_kill: inc esi
stdcall find_session,esi
or eax, eax
jnz kill_ok
ret
kill_ok: xchg eax, edi
invoke closesocket,dword [edi+16]
stdcall send_data,[master],msg_kill,edi,0
ret
; ************* PROCESS PRIVMSG FROM CLIENT *************************
process_privmsg_client:
lodsd
or eax, 020202020h
cmp eax, "msg "
jz privmsg_client_ok
ret
privmsg_client_ok:
lodsb
cmp al, "#"
jz client_privmsg_channel
call load_privmsg
stdcall send_data, [master],master_privmsg,edx,esi
ret
client_privmsg_channel:
call load_privmsg
stdcall send_data, [master],channel_privmsg,edx,esi
ret
load_privmsg: lodsb
cmp al, ":"
jnz load_privmsg
sub ecx, ecx
dec ecx
findend_cpc: inc ecx
cmp byte [esi+ecx], 13
ja findend_cpc
mov byte [esi+ecx], 0
ret
; ############# CLIENT SESSION FUNCTIONS ############################
; ************* ADD SESSION *****************************************
; push sockethandle
; push ip
; push nick
add_session: push esi edi
mov edi, clients-20
mov esi, [esp+8+4]
find_empty_session:
add edi, 20
cmp dword [edi], 0
jnz find_empty_session
mov eax, [esp+8+4+8] ; eax = sockethandle
mov [edi+16], eax
mov eax, [esp+8+4+4] ; eax = ip
mov [edi+12], eax ; save ip address
mov ecx, 3
rep movsd ; copy nickname
pop edi esi
ret 12
; ************* FIND SESSION ****************************************
; push nick
find_session: push esi edi ecx
mov esi, clients-20
mov edi, [esp+12+4]
mov ecx, max_connections
find_nick_session:
add esi, 20
push esi edi ecx
cmp byte [esi+4], 0
jz not_session
compare_sessions:cmpsb
jnz not_session
cmp byte [esi], 0
jnz compare_sessions
cmp byte [edi], 0
jz nick_session_found
not_session: pop ecx edi esi
loop find_nick_session
sub eax, eax
jmp find_session_done
nick_session_found:
pop ecx edi esi
xchg eax, esi
find_session_done:
pop ecx edi esi
ret 4
; ************* REMOVE SESSION **************************************
; push nick
remove_session: push edi ecx
stdcall find_session,dword [esp+8+4]
or eax, eax
jz remove_session_done
xchg edi, eax
mov ecx, 3
sub eax, eax
rep stosd
inc eax
remove_session_done:
pop ecx edi
ret 4
; ############# SEND DATA ###########################################
; push %i
; push %x
; push data
; push socket
send_data: push edi esi
mov edi, sbuffer
mov esi, [esp+8+4+4]
assemble_data: cmp byte [esi], 0
jz data_assembled
cmp word [esi], "%x"
jz assemble_x
cmp word [esi], "%i"
jz assemble_i
movsb
jmp assemble_data
assemble_i: push esi
mov esi, [esp+12+4+12]
jmp copy_x
assemble_x: push esi
mov esi, [esp+12+4+8]
copy_x: movsb
cmp byte [esi], 0
jnz copy_x
pop esi
inc esi
inc esi
jmp assemble_data
data_assembled: sub edi, sbuffer
mov eax, [esp+8+4]
invoke send,eax,sbuffer,edi,0
pop esi edi
ret 16
; ************* FUNCTION CONVERT IP *********************************
; eax = session
convert_to_ip: push esi edi ecx
xchg eax, esi
lea eax, [esi+12] ; eax = ip addr
invoke gethostbyaddr,eax,4,PF_INET
push eax
mov edi, rip
copy_nick_join: movsb
cmp byte [esi], 0
jnz copy_nick_join
mov ax, "!@"
stosw
pop eax
cmp eax, 0
jz skip_ip
mov esi, [eax]
copy_addr_join: movsb
cmp byte [esi], 0
jnz copy_addr_join
skip_ip: sub eax, eax
stosb
pop ecx edi esi
ret
; ############# DATA ################################################
welcome_msg db ":server 001 %x :Welcome to this server %x",13,10
db ":%x!_@server JOIN #main",13,10
db ":server 353 %x = #main :%x @server",13,10
db ":server 366 %x #main :End of /NAMES list",13,10,0
oper_msg db ":server!@server MODE #main +o :%x",13,10,0
join_msg db ":%x JOIN #main",13,10,0
master_privmsg db ":%x!@server PRIVMSG server :%i",13,10,0
channel_privmsg db ":%x!@server PRIVMSG #main :%i",13,10,0
server_privmsg db ":server!@server PRIVMSG %x :%i",13,10,0
master_channel_privmsg db ":server!@server PRIVMSG #main :%x",13,10,0
quit_msg db ":%x!@server QUIT :Connection closed",13,10,0
msg_kill db ":server!@server KICK %x :Banned",13,10,0
lookup_host db "NOTICE AUTH :*** Looking up your hostname",13,10,0
whois_msg db ":server 311 master %x ~user %i * :Userdata",13,10
db ":server 318 master %x :End of /WHOIS list.",13,10,0
.end start
|