; ######################################################################### ; # IRC Socket stuff ; ######################################################################### include asmIRC.inc ; ######################################################################### .const szIRC_SERVER db "server",0 DEFAULT_IRC_PORT EQU 6667 ; format strings szFORMAT_CONNECTED db "Connected to IRC server: %s port %u",0 szFORMAT_LOGIN db "USER %s localhost server :%s",13,10,"NICK %s",13,10,0 ;,"MOTD",13,10,0 ; error messages szERROR_GETHOSTNAME db "ERROR: gethostbyname failed, network not working?",0 szERROR_CONNECTION db "ERROR: Connection failed!",0 szERROR_DISCONNECTED db "ERROR: Disconnected",0 szERROR_SEND db "ERROR: Sending failed!",0 .data? szIRCCommand db MAX_STRLEN dup (?) ; the irc command szIRCOptions db MAX_STRLEN dup (?) ; the irc options szIRCServer db MAX_STRLEN dup (?) ; the irc server sin sockaddr_in <> ; szBuffer db MAX_STRLEN dup (?) ; szOutput db MAX_STRLEN dup (?) szInput db 01000h dup (?) .data extrn szAbout :byte ; in WndProc.asm szIRCNick db "asmIRC",0 ;db 10 dup (?) ; the irc nick (max 9 chars + zero) extrn hStatus :DWORD ; in WndProc.asm public hIRCSocket ; for use in WndProc.asm hIRCSocket dd 0 ; the main IRC socket wIRCPort dw DEFAULT_IRC_PORT ; the IRC port to use fConnected dd 0 ; connected flag fOutputWaiting dd 0 ; stuff in szOutBuffer flag .code ; ######################################################################### ; # OnConnect, called right after connection is established, ideally on ; # a WM_SOCKET + FD_CONNECT message for an async socket. ; ######################################################################### OnConnect proc inc fConnected xor eax, eax mov ax, wIRCPort invoke wsprintf, ADDR szBuffer, ADDR szFORMAT_CONNECTED, ADDR szIRCServer, eax invoke SetWindowText, hStatus, ADDR szBuffer invoke wsprintf, ADDR szBuffer, ADDR szFORMAT_LOGIN, ADDR szIRCNick, ADDR szAbout, ADDR szIRCNick invoke lstrlen, ADDR szBuffer invoke send, hIRCSocket, ADDR szBuffer, eax, 0 invoke AddViewString, ADDR szBuffer ret OnConnect endp ; ########################################################## ; ######################################################################### ; # OnDisconnect, called right after connection is closed, ideally on ; # a WM_SOCKET + FD_CLOSE message for an async socket. ; ######################################################################### OnDisconnect proc dec fConnected invoke AddViewString, ADDR szERROR_DISCONNECTED invoke SetWindowText, hStatus, ADDR szERROR_DISCONNECTED ret OnDisconnect endp ; ####################################################### ; ######################################################################### ; # ReadSocket called when there is data to read from the socket. ; # usually on WM_SOCKET + FD_READ ; ######################################################################### ReadSocket proc LOCAL available_data :DWORD ; LOCAL actual_data_read :DWORD invoke ioctlsocket, hIRCSocket, FIONREAD, addr available_data .if (eax==NULL) invoke recv, hIRCSocket, ADDR szInput, available_data, 0 mov ecx, eax ; ecx=sizeof inbuf mov ebx, eax lea esi, szInput mov edi, esi cld @L1: lodsb .if (al==0Ah) || (al==0Dh) mov byte ptr [esi-1],0 .endif dec ecx jnz @L1 mov ecx, ebx mov al,0 mov edx, edi @L2: repnz scasb pusha invoke AddViewString, edx popa repz scasb ; skip any 0s between strings... mov edx, edi dec edx cmp ecx,0 jne @L2 .endif ret ReadSocket endp ; ######################################################### ; ######################################################################### ; # WriteSocket called when the socket is ready for writing. ; # usually on WM_SOCKET + FD_WRITE ; ######################################################################### WriteSocket proc ret WriteSocket endp ; ######################################################## ; ######################################################################### ; # SendIRCString sends a string to the socket. ; ######################################################################### SendIRCString proc lpszString:DWORD .if fConnected==1 .if fOutputWaiting==TRUE ; then append string to buffer .else invoke lstrlen, lpszString inc eax push eax invoke lstrcpyn, ADDR szOutput, lpszString, eax lea ebx, szOutput pop eax add ebx, eax mov word ptr [ebx],0A0Dh add ebx,2 mov byte ptr [ebx],0 add eax,2 invoke send, hIRCSocket, ADDR szOutput, eax, 0 .if eax==SOCKET_ERROR invoke AddViewString, ADDR szERROR_SEND .endif .endif ; mov fOutputWaiting,TRUE .endif ret SendIRCString endp ; ###################################################### ; ######################################################################### ; # IRCCommand processes IRC commands from the edit box. ; # (those that begin with '/') ; ######################################################################### IRCCommand proc lpszString:DWORD invoke GetWordLength, lpszString inc lpszString ; save the command invoke lstrcpyn, ADDR szIRCCommand, lpszString, eax invoke GetWordPtr, lpszString, 2 ; get pointer to 2nd word push eax invoke lstrlen, eax ; get length of the remaining string .if eax==0 ; if no more then no options, exit. ret .endif pop ebx ; ebx = pointer to 2nd word in lpszString ; eax = length of the string from 2nd word inc eax ; make room for zero termination ; save the options invoke lstrcpyn, ADDR szIRCOptions, ebx, eax ; server invoke lstrcmpi, ADDR szIRCCommand, ADDR szIRC_SERVER .if eax==0 ; equal, so command="/server ..." invoke GetWordLength, ADDR szIRCOptions inc eax invoke lstrcpyn, ADDR szIRCServer, ADDR szIRCOptions, eax invoke GetWordPtr, ADDR szIRCOptions, 2 ; get pointer to port push eax invoke lstrlen, eax pop ebx ; .if eax!=0 ; invoke atoi, ebx ; mov wIRCPort,ax ; .else ; mov wIRCPort, DEFAULT_IRC_PORT ; .endif invoke SetWindowText, hStatus, ADDR szIRCServer mov sin.sin_family, AF_INET invoke htons, wIRCPort ; convert port number into network byte order first mov sin.sin_port,ax ; note that this member is a word-size param. invoke gethostbyname, addr szIRCServer .if eax!=NULL mov eax,[eax+12] ; move the value of h_list member into eax mov eax,[eax] ; copy the pointer to the actual IP address into eax mov eax,[eax] ; copy IP address into eax mov sin.sin_addr,eax invoke connect, hIRCSocket, ADDR sin, sizeof sin .if eax==SOCKET_ERROR ; assuming we use non-blocking mode, connect ; will always return SOCKET_ERROR invoke WSAGetLastError ; retrieve the actual error code .if eax!=WSAEWOULDBLOCK ; if it's not WSAEWOULDBLOCK ; it means a true error occurred invoke AddViewString, ADDR szERROR_CONNECTION .else .endif .endif .else invoke AddViewString, ADDR szERROR_GETHOSTNAME .endif .endif ret IRCCommand endp ; ######################################################### end