flat assembler
Message board for the users of flat assembler.
 Home   FAQ   Search   Register 
 Profile   Log in to check your private messages   Log in 
flat assembler > Windows > Picnic Playground

Author
Thread Post new topic Reply to topic
Picnic



Joined: 05 May 2007
Posts: 1198
Location: Athens, Greece
Picnic Playground
Chat is a very simple console application to provide a direct communication between two computers in the same peer to peer environment.
It uses UDP sockets, the winsock api and C library calls and is tested on Windows XP on my home network as my work also.
I had it unfinished on my hard disk for quite some time.

Command line parameters syntax like this: listen_port destination_machine destination_port

Example using hostnames.
on my laptop: chat 1024 desktop 1025
on my pc: chat 1025 laptop 1024

Example using IP address.
on my laptop: chat 1024 192.168.1.102 1025
on my pc: chat 1025 192.168.1.101 1024


Code:

;-------------------------------------------------------------------------
;   CHAT.ASM
;   Win32 Console Application
;-------------------------------------------------------------------------
;   Application uses the User Datagram Protocol (UDP)
;   to provide a direct communication between 2
;   computers in a peer to peer like environment.
;-------------------------------------------------------------------------
;   Fasm v1.69.20
;   20 Sep 2010, Picnic
;-------------------------------------------------------------------------

    format pe console
    entry main

    include "include\win32ax.inc"

section ".idata" import data readable writeable

    library\
    kernel32,"kernel32.dll",\
    user32,"user32.dll",\
    ws2_32,"ws2_32.dll",\
    msvcrt,"msvcrt.dll"

    include "include\api\kernel32.inc"
    include "include\api\user32.inc"

    import ws2_32,\
    gethostbyname,"gethostbyname",\
    gethostbyaddr,"gethostbyaddr",\
    WSAGetLastError,"WSAGetLastError",\
    WSAStartup,"WSAStartup",\
    WSACleanup,"WSACleanup",\
    closesocket,"closesocket",\
    inet_ntoa,"inet_ntoa",\
    inet_addr,"inet_addr",\
    recvfrom,"recvfrom",\
    sendto,"sendto",\
    socket,"socket",\
    listen,"listen",\
    bind,"bind",\
    htonl,"htonl",\
    htons,"htons",\
    ntohs,"ntohs"

    import msvcrt,\
    __getmainargs,"__getmainargs",\
    _beginthreadex,"_beginthreadex",\
    memset,"memset",\
    strcpy,"strcpy",\
    strlen,"strlen",\
    printf,"printf",\
    fgets,"fgets",\
    fflush,"fflush",\
    atoi,"atoi",\
    _iob,"_iob"

;-------------------------------------------------------------------------
;
section ".data" data readable writeable
;
;-------------------------------------------------------------------------

    MAX_SIZE = 2048
    INVALID_SOCKET = 0xFFFFFFFF
    crlf equ 0x0D,0x0A

    argc dd ?
    argv dd ?
    env dd ?
    listen_socket dd ?
    listen_port dd ?
    dest_port dd ?
    dest_name rb 256
    buffer rb MAX_SIZE

    align 4
    saddr sockaddr_in
    WSAData WSADATA

;-------------------------------------------------------------------------
;
section ".text" code readable executable
main:
;
;-------------------------------------------------------------------------

    cinvoke __getmainargsaddr argcaddr argvaddr env0
    .if ( dword [argc] = 4 )
        mov ebx, [argv]
        cinvoke atoidword [ebx+04h]
        mov dword [listen_port], eax
        push eax
        cinvoke atoidword [ebx+0Ch]
        mov dword [dest_port], eax
        pop ecx
    .endif

    ; Make sure data passed on command line is correct
    .if ( dword [argc] <> 4 | ~eax | ~ecx | eax > 65535 | ecx > 65535 | eax = ecx )
        cinvoke printf, <"Usage: chat [listen port] [destination machine] [destination port]",crlf>
        mov eax1
        ret
    .endif

    ; Save the destination machine's address/name
    cinvoke strcpyaddr dest_namedword [ebx+08h]

    cinvoke printf, <"Initializing...",crlf>

    ; Starts the Winsock service
    invoke WSAStartup0202haddr WSAData
    .if ( eax <> 0 )
        cinvoke printf, <"WSAStartup failed",crlf>
        mov eax1
        ret
    .endif

    ; Try to listen to requested port
    stdcall TryListendword [listen_port]
    .if ( ~eax )
        cinvoke printf, <"Error listening to port %d",crlf>, dword [listen_port]
        mov ebx1
    .else
        cinvoke printf, <"chat ready: <Ctrl-C> to exit",crlf>
        cinvoke fgetsaddr bufferMAX_SIZEdword [_iob]

        .while ( eax <> 0 )
            ; Forward the sendbuf to destination machine
            ; Continue to grab input from stdin
            cinvoke strlenaddr buffer
            stdcall SendMsgaddr buffereaxaddr dest_namedword [dest_port]
            cinvoke fgetsaddr bufferMAX_SIZEdword [_iob]
        .endw

        xor ebxebx
    .endif

    .if ( dword [listen_socket] <> INVALID_SOCKET )
        invoke closesocketdword [listen_socket]
    .endif

    invoke WSACleanup
    invoke ExitProcessebx
    ret

;-------------------------------------------------------------------------
;
;   SendMsg()
;
;-------------------------------------------------------------------------

align 4
proc SendMsg uses ecx ebx edx,\
sendbuf:dwordsendlen:dwordhost:dwordport:dword

    local ipaddr dd ?
    local to sockaddr_in

    ; Is the host passed a name?
    cinvoke atoidword [host]
    .if ( ~eax )
        invoke gethostbyname, [host]
    .else
        ; Otherwise, assume it's IP format
        cinvoke inet_addrdword [host]
        mov dword [ipaddr], eax
        invoke gethostbyaddraddr ipaddr4AF_INET
    .endif

    .if ( ~eax )
        invoke WSAGetLastError
        cinvoke printf, <"Error getting host address - code: %ld",crlf>, eax
        xor eaxeax
        ret
    .endif

    virtual at eax
        .hostdata hostent
    end virtual
    mov eax, [.hostdata.h_addr_list]
    mov eax, [eax]
    mov eax, [eax]

    ; Endpoint address of the destination computer
    mov dword [to.sin_addr], eax
    mov dword [to.sin_family], AF_INET
    invoke htonsdword [port]
    mov word [to.sin_port], ax

    cinvoke printf, <"Message being sent to host %s port %d",crlf>, dword [host], dword [port]

    invoke sendtodword [listen_socket], dword [sendbuf], dword [sendlen], 0addr tosizeof.sockaddr_in

    .if ( eax > dword [sendlen] | eax = INVALID_SOCKET )
        cinvoke printf, <"Error sending UDP packet from listen socket",crlf>
        xor eaxeax
        ret
    .endif

    mov eax1
    ret
endp

;-------------------------------------------------------------------------
;
;   TryListen()
;
;-------------------------------------------------------------------------

align 4
proc TryListen uses ecx ebx edxport:dword

    local thread dd ?

    mov dword [listen_socket], INVALID_SOCKET

    ; This socket uses the User Datagram Protocol (UDP)
    invoke socketAF_INETSOCK_DGRAM17
    .if ( eax = INVALID_SOCKET )
        cinvoke printf, <"Error: listen socket creation failed",crlf>
        xor eaxeax
        ret
    .endif

    mov dword [listen_socket], eax

    mov dword [saddr.sin_family], AF_INET
    invoke htonl0 ; any address
    mov dword [saddr.sin_addr], eax
    invoke htonsdword [port]
    mov word [saddr.sin_port], ax

    invoke binddword [listen_socket], addr saddrsizeof.sockaddr_in
    .if ( eax <> 0 )
        cinvoke printf, <"Error: bind on listen socket failed",crlf>
        invoke closesocketdword [listen_socket]
        xor eaxeax
        ret
    .endif

    cinvoke _beginthreadex00addr ListenThreaddword [listen_socket], 0addr thread
    .if ( ~eax )
        cinvoke printf, <"Error creating listen thread",crlf>
        xor eaxeax
        ret
    .endif

    invoke CloseHandleeax

    mov eax1
    ret
endp

;-------------------------------------------------------------------------
;
;   ListenThread()
;
;-------------------------------------------------------------------------

align 4
proc ListenThread uses ecx ebx edxs:dword

    local from_len dd ?
    local from sockaddr_in
    local recvbuf rb MAX_SIZE+100

    .while ( 1 )    ; loop forever

        mov [from_len], sizeof.sockaddr_in
        cinvoke memsetaddr recvbuf0MAX_SIZE
        invoke recvfromdword [s], addr recvbufMAX_SIZE-10addr fromaddr from_len

        .if ( signed eax > 0 )

            lea ebxdword [recvbuf]
            mov byte [ebx+eax], 0

            invoke inet_ntoadword [from.sin_addr]
            push eax
            movzx eaxword [from.sin_port]
            invoke ntohseax
            pop ecx

            cinvoke printf, <"Message received from host %s port %d",crlf>, ecxeax
            cinvoke printf">> %s"addr recvbuf

        .endif

    .endw

    ret
endp




Last edited by Picnic on 29 Aug 2014, 20:54; edited 5 times in total
Post 20 Sep 2010, 20:29
View user's profile Send private message Reply with quote
Overflowz



Joined: 03 Sep 2010
Posts: 1047
Oh, so nice ! BTW can you write more simple code without command line args and without proc-s ? just like when conencted to wait for recive or send and client/server same like that. thank you! Smile
Post 21 Sep 2010, 11:20
View user's profile Send private message Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4156
Location: https://pastebin.com/Vw7WXXf4
and for IRC?
Post 21 Sep 2010, 11:35
View user's profile Send private message Visit poster's website Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1198
Location: Athens, Greece
Hi,

Overflowz, __getmainargs function provides a simple way to get the command line parameters.
As better alternatives see Windows API functions GetCommandLine or CommandLineToArgvW
Search fasm board for examples or even more simple winsock samples.

edfed i don't know much about IRC, never used it.
Post 22 Sep 2010, 11:26
View user's profile Send private message Reply with quote
Overflowz



Joined: 03 Sep 2010
Posts: 1047
Okay thanks. Smile I'm just stuck how to receive buffer and I know only send >.<
Post 22 Sep 2010, 12:55
View user's profile Send private message Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1198
Location: Athens, Greece
A simple Winsock Multi-User Console Chat Server.
Made for Windows XP, tested with telnet.exe, putty client will also work.
It can handle backspace, users can change their names, it prints a user-list. Program is inspired from a C++ sample.
The listening port can be passed as a command line argument, the default port is 23. Esc stops the server.
Despite my lame code which is written in three days, it works well.

Image


Last edited by Picnic on 29 Aug 2014, 21:24; edited 2 times in total
Post 22 Jul 2012, 21:51
View user's profile Send private message Reply with quote
sleepsleep



Joined: 05 Oct 2006
Posts: 6578
Location: ˛                              ⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣ Posts: 6699
looks great!!
Post 23 Jul 2012, 00:40
View user's profile Send private message Reply with quote
bzdashek



Joined: 15 Feb 2012
Posts: 147
Location: Tolstokvashino, Russia
Yeah, wonderful!
Post 23 Jul 2012, 05:48
View user's profile Send private message Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1198
Location: Athens, Greece
thank you both, appreciate the comments.
Post 24 Jul 2012, 05:06
View user's profile Send private message Reply with quote
bzdashek



Joined: 15 Feb 2012
Posts: 147
Location: Tolstokvashino, Russia
Where did the last version go?
Post 26 Aug 2012, 07:32
View user's profile Send private message Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1198
Location: Athens, Greece
I thought to make it better, a login system with username and password for each account would be nice but to be honest i'm bored now. Feel free to modify source as you wish.
Ansi colors were added, exploited the fact that clients like telnet.exe are forgiving, and overlook that proper use requires an exchanging information first. Also a server log added.
Here you are, sorry for any inconvenience.


Silent Edit
I started re-writing the chat program. I upload new sources as soon as possible.

Image


Description:
Download
Filename: CHAT.zip
Filesize: 22.24 KB
Downloaded: 88 Time(s)



Last edited by Picnic on 29 Aug 2014, 20:49; edited 3 times in total
Post 26 Aug 2012, 10:44
View user's profile Send private message Reply with quote
bzdashek



Joined: 15 Feb 2012
Posts: 147
Location: Tolstokvashino, Russia
Thank you, Picnic!
Post 26 Aug 2012, 10:47
View user's profile Send private message Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1198
Location: Athens, Greece
You're welcome bzdashek!


Last edited by Picnic on 03 Mar 2013, 19:55; edited 1 time in total
Post 12 Jan 2013, 16:24
View user's profile Send private message Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
When working on such projects consider using multi-threaded libraries with callback support (Windows has one for GUI but kind of sucks).

Example.

Make a library that can be re-used (duh)

Pseudo code

Code:


; import winsock

; Define our interface here. Just a struct

struct ISocketEvent
         onDataArrival   dd ? ; implement as proc onDataArrival, handle, lpData, dwSize
         onClientReady dd ? ; implement as proc onClientReady, handle, lpData, lpdwSize   ; return data to send and size in the last two parameters. (See below)
         onError           dd ? ; implement as proc onError, dwCode, pszDecription
         onConnect      dd ? ; implement as proc onConnect, handle, pszRemoteHost, dwPort
         onDisconnect   dd ? ; implement as proc onDisconnect, handle
ends

; Object identifiers
struct  SocketObject
          .socket   dd 0             ; socket handle
          .sai        sockaddr_in 
          .stop      dd 1             ; connection state (closed, this stops the loop)
          .ISocketEventPtr         ; the callback table pointer to user functions
endp


; impl

proc Startup
        ... winsock initialization here
endp 

/// Returns a handle (Basically a pointer to SocketObject struct)
proc Connect pszIP_or_DNSportiCallbackPtr

 
      handle =    memalloc SocketObject.Size

      handle.sai.port = port;
      handle.ISocketEventPtr = iCallbackPtr

      ... start connection thread
      CreateThread.. ConnectionThreadhandle

      return handle
endp
proc ConnectionThreadhandle
        ..winsock connection functions here


         handle.socket = socket(...);
           .. if error call  handle.ISocketEventPtr.onErrorsocket_error_code"Custom or system description"

        .. if connection made
             call  handle.ISocketEventPtr.onConnecthandlepszHostNameport
                          
             CreateThreadMonitorThreadhandle )

       .. if not
             call handle.ISocketEventPtr.onErrorsocket_error_code"Custom or system description"

       .. this thread exits
endp


/// Returns a handle (Basically a pointer to SocketObject struct)
proc ListenportiCallbackPtr
              handle = memalloc , SocketObject.Size

              handle.sai.port = port
              handle.ISocketEventPtr = iCallbackPtr

             // start listening thread
endp

proc ListenThreadhandle
         while handle.stop = false
                 // you know the drill here boys
         end while
endp

proc MonitorThreadhandle

      while handle.stop = false

      fd_set read_set.
      fd_set write_set.
      fd_set error_set.

      // check states here

      ..if(read_set)
         dwBytes = 0
         ioctlsocket(handle.socketFIONREADdwBytes); .. available bytes to read
         
         buffer = memalloc dwBytes
         .. if not
             call handle.ISocketEventPtr.onErrorcustom_error_code"Custom or system description"

         ..else
             recv(handle.socketbufferdwBytes)
             .. if not 
                 call handle.ISocketEventPtr.onErrorsocket_error_code"Custom or system description"
             .. else
                 call handle.ISocketEventPtr.onDataAvailablehandlebufferdwBytes
                    if(buffer !null)    ; in case user did something stupid with the buffer
                         memfree(buffer)
                

      .. if(write_set)
          dwSize = 0
          lpBuffer0
          buffer = call handle.ISocketEventPtr.onClientReadyhandlebufferdwSize

         if(buffer !null and dwSize > 0 )
            send(handle.socketbufferdwSize);

         .. if not
             call handle.ISocketEventPtr.onErrorsocket_error_code"Custom or system description"

      if(error_set)
           get error code
            call handle.ISocketEventPtr.onErrorsocket_error_code"Custom or system description"

      // check MSDN for more on how to check for a closed/disconnected socket
      if(read_set && <some other byte checks>)
           call handle.ISocketEventPtr.onDisconnectedhandle
           exit here
           break;

         // pause or sleep here

      end while

        closesocket handle.socket
endp

proc FreeHandlehandle
         memfreehandle
endp

proc Closehandle
        handle.stop = true // this will stop the thread
endp

; exports

Startup
Connect
Listen
Send
Close
FreeHandle






Using it

Code:


; setup GUI
myGui.setup;

libSocket.Statup


proc onDataArrivalhandlebytessize
         if(handle = my_handle)  ; of course you'd know how to do this
           myGui.RichEdit.Text.Append(bytes)
endp

proc onDisconnect
         myGui.Button.Connect.Enabled = true;
endp

my_handle dd 0
proc myGui.button.Connent.Click
          host = myGui.Edit.Host.Text
          port = intmyGui.Edit.Port.Text )
           my_handle = libSOcket.Connecthostport
endp





Well that's about it. Sorry if it seems like nonsense but someone one day will find it useful. I'm currently developing on android and I'm using threads quite extensively so I often use interfaces to make things flow better other than having to wait for a function/method to return.
Post 13 Jan 2013, 00:35
View user's profile Send private message Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1198
Location: Athens, Greece
@typedef no, it doesn't seem nonsense, suggestions and pseudocode are welcome.
I do have a multi-user chat program on which i used threads but is left unfinished.
I have little reusable code in asm, programs above are more like simple learning excercises, practicing C/C++ and asm simultaneously.
Post 15 Jan 2013, 12:40
View user's profile Send private message Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
Lol. No source code?

And what's up with the CryptXXX functions?
Post 05 Mar 2015, 02:07
View user's profile Send private message Reply with quote
catafest



Joined: 05 Aug 2010
Posts: 78
Windows defender see this like malware

Picnic wrote:
I thought to make it better, a login system with username and password for each account would be nice but to be honest i'm bored now. Feel free to modify source as you wish.
Ansi colors were added, exploited the fact that clients like telnet.exe are forgiving, and overlook that proper use requires an exchanging information first. Also a server log added.
Here you are, sorry for any inconvenience.


Silent Edit
I started re-writing the chat program. I upload new sources as soon as possible.

Image

Post 07 May 2017, 23:11
View user's profile Send private message Yahoo Messenger Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1198
Location: Athens, Greece
Unfortunately many of my fasm console programs that using sockets are recognized as viruses. I can not resolve this.
Post 09 May 2017, 06:46
View user's profile Send private message Reply with quote
catafest



Joined: 05 Aug 2010
Posts: 78

Picnic wrote:
Unfortunately many of my fasm console programs that using sockets are recognized as viruses. I can not resolve this.


I think the problem is the format of :

Code:
pe console


, I don't have your source code for CHAT.rar
If you make a search on this forum will see how to fix that.
Nice ideea if you will update this with useful tools under Windows OS ...
Make a brainstroming about how can be usefull your application Smile
Post 09 May 2017, 10:59
View user's profile Send private message Yahoo Messenger Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >

Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001-2005 phpBB Group.

Main index   Download   Documentation   Examples   Message board
Copyright © 2004-2016, Tomasz Grysztar.