Liberty BASIC Community Forum
Special Topics and Projects >> Internet and network programming >> Command server
http://libertybasic.conforums.com/index.cgi?board=internet&action=display&num=1378001461

Command server
Post by Dan Teel on Aug 31st, 2013, 9:11pm

I've created a DLL that lets you create a "command" server. The dll and demo .bas file is located here.

http://zptr.net/software/zptrcs.zip

and here is the demo code for quick reference.
Code:
    nomainwin
    WindowWidth = 550
    WindowHeight = 410
    UpperLeftX=int((DisplayWidth-WindowWidth)/2)
    UpperLeftY=int((DisplayHeight-WindowHeight)/2)

    'Make our dummy buttons that will be clicked when the appropriate cmd is recvd.
    button #main.close,"",[quit.main], UL,   -102,   2,  62,  25
    button #main.sayhi,"",[sayhi], UL,   -105,  48,  65,  25

    open "zptrcs Test" for window as #main
    print #main, "font ms_sans_serif 10"
    print #main, "trapclose [quit.main]"

    'Open the zptrcs dll
    open "zptrcs.dll" for DLL as #zcs

    'Start the command server on port 80
    if StartCmdServer(80)<>0 then
        notice "Error starting command server!"
    end if

    'Set the html that the server will send clients, this is optional
    call SetHTML "<html><body><a href='sayhi'>Say hi!</a><br><a href='close'>Close the program</a></body></html>"

    'Add the commands. The commands must be alpha-numeric characters. no spaces or symbols.
    'Then also, specify the hwnd of the button you want clicked when that command is recvd.
    'Note: the commands are case-INsensitive
    lpSayHi=AddCmd("sayhi",hwnd(#main.sayhi))
    lpClose=AddCmd("close",hwnd(#main.close))
    wait

[sayhi]
    'Remove the 'sayhi' command after its called, so it will effecively be called only once
    call RemoveCmd lpSayHi
    notice "Hi!"
    wait

[quit.main]
    call StopCmdServer'Stop the server now that we are done
    call FreeCmds'Removes all commands.
    close #zcs
    close #main
    end

function StartCmdServer(port)'returns zero if no error
    calldll #zcs,"StartCmdServer",_
        port as ulong,_
        StartCmdServer as long
end function

sub StopCmdServer'Stops the command server
    calldll #zcs,"StopCmdServer",ret as void
end sub

sub FreeCmds'Deletes all the commands.
    calldll #zcs,"FreeCmds",ret as void
end sub

function AddCmd(command$,buttonHwnd)'Returns address of command in memory
    calldll #zcs,"AddCmd",command$ as ptr,_
        buttonHwnd as ulong,_
        AddCmd as ulong
end function

sub RemoveCmd lpCommand'Removes the specified command
    calldll #zcs,"RemoveCmd",_
        lpCommand as ulong,_
        ret as void
end sub

sub SetHTML html$'Sets the webpage to display the client.
    calldll #zcs,"SetHTML",_
        html$ as ptr,_
        ret as void
end sub
 


This would be good for having communication between a cell phone and your computer.

You would pretty much go to your web browser and type in 127.0.0.1 (your IP address). This will bring up the web page you specify in your program (you can make a webpage with links to do your commands.)

To send a command to the server then you simple do it as such

127.0.0.1/command

You just specify the command right after the ip address.

Its dificult for me to really explain this all, but I hope the demo program will explain it to ya.
Re: Command server
Post by Brandon Parker on Aug 31st, 2013, 9:29pm

Dan,

I have not used this yet, but it seems very interesting and I may have use for it in the future. Thanks for posting it!!

My only question is that instead of using dummy buttons could you change the DLL to accept the address of a CallBack function set up in LB and then send information to the function as to what action the user has performed?


{:0)

Brandon
Re: Command server
Post by Dan Teel on Sep 1st, 2013, 12:01pm

Yes that is possible and it would be easy to implement, I'm just not to big a fan on callbacks in LB as I've always experienced weird issues when using them in the past. But with this volume of traffic I'm sure I wouldn't experience any of those issues.

I'll work on it tonight and I'll make it an option when adding commands to either press a dummy button or do a callback.
Re: Command server
Post by RichardRussell on Sep 1st, 2013, 4:01pm

on Sep 1st, 2013, 12:01pm, Dan Teel wrote:
I'm just not to big a fan on callbacks in LB

I share your concern, and I too have experienced issues (which I have often blamed on LB not managing to process them quickly enough).

I don't know how callbacks are implemented internally, but the implications for serialising operations such as accesses to global variables sound quite problematic to me.

Richard.
Re: Command server
Post by Brandon Parker on Sep 1st, 2013, 7:22pm

While there are issues with LB's CallBacks I have yet to have real problems using the ones that can be used as long as they are written correctly. I guess it's all up to what is being performed.....

Thanks for making that an option; hopefully I'll get around to playing with it before too long.


{:0)

Brandon
Re: Command server
Post by RichardRussell on Sep 2nd, 2013, 01:46am

on Sep 1st, 2013, 7:22pm, Brandon Parker wrote:
While there are issues with LB's CallBacks I have yet to have real problems using the ones that can be used as long as they are written correctly.

Do you happen to know how LB reacts if a second callback occurs whilst the first one is still being processed, i.e. the user's handler is being executed?

Does the second callback 'interrupt' the first (i.e. are they re-entrant), are they serialised so that the second one is processed as soon as the first one has completed, or what?

Richard.
Re: Command server
Post by Brandon Parker on Sep 2nd, 2013, 11:13am

I cannot say for certain, but I believe the CallBacks get serialized. Working with Windows' timers and LB's CallBacks it appears to me that if one CallBack is initiated it must complete prior to the next CallBack starting.

Update: Just doing some more testing and I got differing results using different types of timers. One was serialized and the other more simple timer was not, but it ended up crashing LB with a stack overflow; presumably due to the stacked up timer calls that were not completing.

This is just a guess based on my personal observations though....


{:0)

Brandon
Re: Command server
Post by Mattestion on Sep 2nd, 2013, 4:05pm

on Aug 31st, 2013, 9:11pm, Dan Teel wrote:
This would be good for having communication between a cell phone and your computer.

How would you do that? I tried accessing the web site created by your demo on my cell phone by using the ip address but it didn't work. It works on my PC though.

Also there seems to be an issue (for me) when using the close command in the demo. I get the message "lbpro.exe has stopped working. Looking for a solution..." and then LB is closed by Windows.
Re: Command server
Post by Dan Teel on Sep 2nd, 2013, 4:52pm

You probably need to setup port forwarding on your router or something to that affect.

Im not sure about the issue your having with it giving you the error on close but I will look into it. It sounds like it got stuck in a loop somewhere which would explain why it becomes unresponsive and windows displaying that message.

Have you made any changes to the source code from the demo? Just trying to gather information to duplicate the issue so I can more effectively troubleshoot
Re: Command server
Post by Mattestion on Sep 2nd, 2013, 5:33pm

No changes at all. I ran it as is. You can see my specs in my signature.
Re: Command server
Post by Dan Teel on Sep 2nd, 2013, 5:50pm

on Sep 2nd, 2013, 5:33pm, Mattestion wrote:
No changes at all. I ran it as is. You can see my specs in my signature.


Ok, I dont have access to my computer right now, but if you want too, try removing the free commands call and see if it still freezes.
Re: Command server
Post by Mattestion on Sep 2nd, 2013, 6:24pm

on Sep 2nd, 2013, 5:50pm, Dan Teel wrote:
Ok, I dont have access to my computer right now, but if you want too, try removing the free commands call and see if it still freezes.


Tried your suggestion but it still gives the same result.
Re: Command server
Post by Dan Teel on Sep 2nd, 2013, 7:14pm

Ok, thanks.
Re: Command server
Post by Dan Teel on Sep 3rd, 2013, 6:34pm

@Callbacks

There seems to be an issue with LB and callbacks. When a callback is called when LB is on a wait statement, the windows will no longer call there handlers. For example when you try to close the window to end the program, it wont respond. To resolve this you wouldnt use any wait statements, instead you would setup a loop with a scan and a sleep call.

I'm not a fan of that but I will include callbacks in my next version, just so long as you are aware of that.

@mattestion
I was using a seperate thread inside of the dll to manage the server and I've changed this to a timer. I dont know if this will fix your issue but its still running fine on my machine so who knows what itll do for yours. I'm sure a timer isnt the most appropriate solution but what is.
Re: Command server
Post by Dan Teel on Sep 3rd, 2013, 7:49pm

Edit: Sorry for the double post. :(

Alright, I've updated the .zip file with the dll and demo.

http://zptr.net/software/zptrcs.zip

below is the source code for the updated demo

Code:
    nomainwin
    WindowWidth = 250
    WindowHeight = 100
    UpperLeftX=int((DisplayWidth-WindowWidth)/2)
    UpperLeftY=int((DisplayHeight-WindowHeight)/2)

    'Make our dummy buttons that will be clicked when the appropriate cmd is recvd.
    button #main.close,"Close",[quit], UL,   100,   2,  100,  25
    button #main.clicked,"Clicked",[clicked], UL,   0,  2,  100,  25

    open "zptrcs Test" for window as #main
    print #main, "font ms_sans_serif 10"
    print #main, "trapclose [quit]"

    'Open the zptrcs dll
    open "zptrcs.dll" for DLL as #zcs

    'start the server on port 80
    if StartCmdServer(80)<>0 then
        notice "Error starting command server!"
    end if

    'set our webpage
    call SetHTML "<html><body align='center' bgColor='#BBBBBB'><br><br><a href="+_
    "'sayhi?.=Oooga+Booga'>Say Oooga Booga</a><br><br><form name='input' action="+_
    "'sayhi' method='get'><input name='.'/><input type='submit' value='Say it!'/>"+_
    "</form><br><form name='input' action='clicked' method='get'><input type='submi"+_
    "t' value='Click the button'/></form><br><a href='close'>Close the program</a>"+_
    "</body></html>"

    'add the commands, you dont need to store these values if you arent
    'going to use the RemoveCmd procedure.
    callback sayhiCB, sayhi(ulong, ulong), void
    lpSayHi=AddCmd("sayhi",0,sayhiCB)
    lpClicked=AddCmd("clicked",hwnd(#main.clicked),0)
    lpClose=AddCmd("close",hwnd(#main.close),0)

    goto [wait]

'our wait work around for callbacks. you dont need to do this if you
'arent using callbacks (as in your only using the button clicks)
[wait]
    calldll #kernel32,"Sleep",10 as ulong,ret as void
    scan
    goto [wait]

'this will be called when you goto 127.0.0.1/clicked
[clicked]
    notice "I was clicked!"
    goto [wait]

'this will be called when you close the window or goto 127.0.0.1/close
[quit]
    call StopCmdServer
    call FreeCmds'Removes all commands.
    close #zcs
    close #main
    end

'The callback is function(ulong,ulong),void
'the first ulong is a pointer to the command
'the second ulong is a pointer to the parameter
'
'to get the server to recognize this the format for the
'URL is 127.0.0.1/COMMAND?.=PARAMETER
'the dll doesnt unmangle the data as of now so you'll need to
'do that manually like decypherURL does.
function sayhi(cmd,param)
    cmd$=winstring(cmd)
    param$=decypherURL$(winstring(param))
    notice cmd$+chr$(13)+param$
end function


'decodes URL
function decypherURL$(txt$)
    gosub [next]
    while l$<>""
        if l$="%" then
            gosub [next]
            a$=l$
            gosub [next]
            a$=a$+l$
            l$=chr$(hexdec(a$))
        end if
        if l$="+" then
            l$=" "
        end if
        decypherURL$=decypherURL$+l$
        gosub [next]
    wend
    exit function
    [next]
    l=l+1
    l$=mid$(txt$,l,1)
    return
end function

'Starts the command server on the specified port
'returns zero if no error
function StartCmdServer(port)
    calldll #zcs,"StartCmdServer",_
        port as ulong,_
        StartCmdServer as long
end function

'stops the command server
sub StopCmdServer
    calldll #zcs,"StopCmdServer",ret as void
end sub

'removes all the commands, you should do this
'everytime to stop the command server in the
'LB enviroment as the dll is not actually freed
'inbetween running your source code so you'll
'keep adding the same commands and it will get
'clogged up with a billion of the same commands.
sub FreeCmds
    calldll #zcs,"FreeCmds",ret as void
end sub

'Adds a command, command$ should be alphanumeric characters
'buttonHwnd should be zero if no button is wanting clicked
'callbAddress should be zero if you dont have a callback setup
function AddCmd(command$,buttonHwnd,callbAddress)'Returns address of command in memory
    calldll #zcs,"AddCmd",command$ as ptr,_
        buttonHwnd as ulong,_
        callbAddress as ulong,_
        AddCmd as ulong
end function

'Removes a specific command
sub RemoveCmd lpCommand
    calldll #zcs,"RemoveCmd",_
        lpCommand as ulong,_
        ret as void
end sub

'Sets the webpage's HTML
sub SetHTML html$
    calldll #zcs,"SetHTML",_
        html$ as ptr,_
        ret as void
end sub
 

Re: Command server
Post by mmiscool on Sep 16th, 2013, 2:05pm

I would be interested in being able to set the html in response to a command. Ie

if the user goto http://myip/show_me_my_todo_list

I could then read in a file and have that be the html response to that. or have it so that it can generate the html page before a response is given.

I have a voice recognition app for android that can relay commands to web server via url encoding. I use it with run basic for home automation via voice control.

As it stands I think this could be used with this project but it would be even better if it could for responses dynamically to the url that is typed.

The thread for my app is on the run basic forum
http://runbasic.proboards.com/index.cgi?action=display&board=announcements&thread=1653&page=1
Re: Command server
Post by Dan Teel on Sep 18th, 2013, 08:26am

I did have that as an option with callbacks but I removed it due to some queer things happening with the callbacks before I realized the whole wait command issue. I might add it back in (I'll have to recode it as I didnt save it) in the future.
Re: Command server
Post by mmiscool on Sep 19th, 2013, 3:46pm

That would be awesome.

I have so many ideas about how this can be used.

I would be very eager come up with some cleaver things to do with it.


Plus this could be used with my home automation system making it easier to be distributed with out the added cost of a full blown license of run basic to do the whole thing

Re: Command server
Post by mmiscool on Jul 12th, 2015, 10:05pm

Sorry to revive an old thread.

I was hoping to find out if there was any thing going on with this?
Re: Command server
Post by michael on Jul 16th, 2015, 08:20am

I am looking carefully at this software.
Is Dan offering this to the Liberty basic community as Open source?
Re: Command server
Post by Dan Teel on Jul 16th, 2015, 3:12pm

Their is nothing going on with this. Heres the source if you wanted it http://www.kcdan.com/zptrcs.zip

Sure open source, why not.

Note: Their is an error in my linked list code, as long as you dont delete any commands that are second or second to last, it should be fine.