From daa40d6367f432ec66f9e9b177a9f283ea49e0b1 Mon Sep 17 00:00:00 2001 From: Christian Damken Date: Wed, 24 Apr 2013 20:25:50 +0200 Subject: [PATCH] warning, buggy version! - class file folder is include/ - moved content handler to an individual class file (include/content.py) - added argument parser (include/argparser.py) -- doesn't work yet like expected --- asrc-server.py | 162 ++++++++++++++++++++++--------------- doc/protocol_reference.odt | Bin 19548 -> 19665 bytes include/__init__.py | 2 + include/argparser.py | 78 ++++++++++++++++++ include/content.py | 78 ++++++++++++++++++ 5 files changed, 255 insertions(+), 65 deletions(-) create mode 100644 include/__init__.py create mode 100644 include/argparser.py create mode 100644 include/content.py diff --git a/asrc-server.py b/asrc-server.py index b65105f..516e42d 100755 --- a/asrc-server.py +++ b/asrc-server.py @@ -25,7 +25,7 @@ # aSRC (Aliased Server Remote Control) # - SERVER - # -# program version: 0.0.0.20130423 +# program version: 0.0.0.20130424 # protocol version: 0.2.20130423 # # @@ -39,75 +39,75 @@ def motd(): return MOTD -def content(client_address, data): - ret = "" +#def content(client_address, data): + #ret = "" - ret = ret + - "{BEGIN}\n"\ - "asrcp" + ProtocolVersion + "\n" + #ret = ret +\ + #"{BEGIN}\n"\ + #"asrcp" + ProtocolVersion + "\n" - # Look if the received message is an - # valid alias or a predefined command + ## Look if the received message is an + ## valid alias or a predefined command - # if it's 'version', return the server and protocol version - if data == "version": + ## if it's 'version', return the server and protocol version + #if data == "version": - if DEBUGLEVEL >= 2: print("Got valid service command from" - + str(client_address) + ": ", data) + #if VERBOSITY >= 2: print("Got valid service command from" + #+ str(client_address) + ": ", data) - ret = ret + - "202 Valid Service Command\n"\ - "002 Version\n"\ - "ServerVersion:" + ServerVersion + "\n"\ - "ProtocolVersion:" + ProtocolVersion + "\n" + #ret = ret +\ + #"202 Valid Service Command\n"\ + #"002 Version\n"\ + #"ServerVersion:" + ServerVersion + "\n"\ + #"ProtocolVersion:" + ProtocolVersion + "\n" - # if it's 'help', give a little help - elif data == 'help': + ## if it's 'help', give a little help + #elif data == 'help': - if DEBUGLEVEL >= 2: print("Got valid command from" - + str(client_address) + ": ", data) + #if VERBOSITY >= 2: print("Got valid command from" + #+ str(client_address) + ": ", data) - # send status code - ret = ret + "202 Valid Service Command\n\n" + ## send status code + #ret = ret + "202 Valid Service Command\n\n" - # send the list of aliases - ret = ret + "Aviable aliases:\n" - for i in aliases.keys(): - ret = ret + str(i) + "\n" + ## send the list of aliases + #ret = ret + "Aviable aliases:\n" + #for i in aliases.keys(): + #ret = ret + str(i) + "\n" - # if it's a valid userdefined command - elif data in aliases: + ## if it's a valid userdefined command + #elif data in aliases: - # send status code - ret = ret + "201 Valid Command\n\n" + ## send status code + #ret = ret + "201 Valid Command\n\n" - # ohmagawd! a debug message!!1! - if DEBUGLEVEL >= 2: print("Got valid command from" - + str(client_address) + ": ", data) + ## ohmagawd! a debug message!!1! + #if VERBOSITY >= 2: print("Got valid command from" + #+ str(client_address) + ": ", data) - # execute the aliased command - g_dict, l_dict = {}, {} - exec(str(aliases[data]), g_dict, l_dict) + ## execute the aliased command + #g_dict, l_dict = {}, {} + #exec(str(aliases[data]), g_dict, l_dict) - # send may contain data to send to the client - if l_dict["send"]: - content = str(l_dict["send"]).replace('{', '\{') - content = content.replace('}', '\}') + ## send may contain data to send to the client + #if l_dict["send"]: + #content = str(l_dict["send"]).replace('{', '\{') + #content = content.replace('}', '\}') - ret = ret + content + "\n" + #ret = ret + content + "\n" - # ALL IS LOST!!1! this has to be invalid! - else: + ## ALL IS LOST!!1! this has to be invalid! + #else: - # send status code - ret = ret + "203 Invalid Command\n" + ## send status code + #ret = ret + "203 Invalid Command\n" - if DEBUGLEVEL >= 2: print("Got invalid command from", - str(client_address), ": ", data) + #if VERBOSITY >= 2: print("Got invalid command from", + #str(client_address), ": ", data) - ret = ret + "{END}\n" + #ret = ret + "{END}\n" - return ret + #return ret class ThreadedRequestHandler(socketserver.StreamRequestHandler): @@ -118,7 +118,7 @@ class ThreadedRequestHandler(socketserver.StreamRequestHandler): self.timeout = TIMEOUT # Print a line with the adress of the connected client - if DEBUGLEVEL >=3: + if VERBOSITY >=3: print("Client connected: " + str(self.client_address)) # send header line 1 @@ -133,7 +133,8 @@ class ThreadedRequestHandler(socketserver.StreamRequestHandler): # content handler self.request.sendall(bytes( - content(str(self.client_address), self.data), ENCODING)) + content.handler(str(self.client_address), self.data, aliases, + ServerVersion, ProtocolVersion, VERBOSITY), ENCODING)) class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): @@ -141,17 +142,46 @@ class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): def main(): + from include import argparser, content + + parser = argparser + args = parser.parse(ServerVersion, ProtocolVersion) + + if os.path.exists("pid"): + if args.delete_pid_file: os.remove("pid") + elif args.allow_multiple_instances: pass + else: + print( + "\npid file already exists\n"\ + "If the server didn't shut down correctly, just delete this file "\ + "or pass -n\n"\ + "If you want to start multiple instances, pass -m\n") + return 1 + + print(args) + + if args.host: HOST = args.host + if args.port: PORT = args.port + if args.timeout: TIMEOUT = args.timeout + if args.encoding: ENCODING = args.encoding + if args.verbosity: VERBOSITY = args.verbosity + + # write pid file + pidf = open("pid", 'w') + pidf.write(str(os.getpid())) + pidf.close() + print("aSRC Server\n"\ - "Server version: " + ServerVersion + "\n"\ - "Protocol version: " + ProtocolVersion + "\n\n"\ - "To stop the server, press Ctrl-C\n") + "Server version: " + ServerVersion + "\n"\ + "Protocol version: " + ProtocolVersion + "\n\n"\ + "To stop the server, press Ctrl-C\n") try: - if DEBUGLEVEL >= 1: print("Initializing server...") + if VERBOSITY >= 1: print("Initializing server...") # Create server server = ThreadedTCPServer((HOST, PORT), ThreadedRequestHandler) - if DEBUGLEVEL >= 1: print("Starting server on", + if VERBOSITY >= 1: print("Starting server on", server.server_address[0], "port", server.server_address[1], "...") # Start a thread with the server -- that thread will then start one # more thread for each request @@ -160,21 +190,23 @@ def main(): # Exit the server thread when the main thread terminates ServerThread.daemon = True ServerThread.start() + while True: time.sleep(10) except KeyboardInterrupt: print("\nGot Ctrl-C, shutting down server...") - try: server.shutdown() + try: + server.shutdown() + os.remove("pid") except: print("Failed to shutdown server correctly, "\ "socket may be still in use or wasn't even started:", sys.exc_info()) - except: - print("\nAn error occured:\n", sys.exc_info(), "\n") + #except: + # print("\nAn error occured:\n", sys.exc_info(), "\n") - - if DEBUGLEVEL >= 3: input("Press Enter to continue\n") + if VERBOSITY >= 3: input("Press Enter to continue\n") return 0 @@ -193,8 +225,8 @@ if __name__ == '__main__': HOST = '127.0.0.1' PORT = 24642 - # Timeout of a connection in seconds - obviously still doesn't work... - TIMEOUT = 4 + # Timeout of a connection in seconds - still doesn't work obviously... + TIMEOUT = 15 # Encoding to be used when communicating with a client ENCODING = 'utf-8' @@ -236,7 +268,7 @@ send = subprocess.check_output(["ping", "-c 2", "fanir.de"]) # Verbosity of logging. # Can be from 0 (only default output) to 3 (debug messages) - DEBUGLEVEL = 3 + VERBOSITY = 3 ############## diff --git a/doc/protocol_reference.odt b/doc/protocol_reference.odt index 174b91b7b8dda8a2ad5d8d88233ed68eeb63378e..f5be414d5b0c55fdd1bc66ddf97b682c564c24b0 100644 GIT binary patch delta 13986 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 Cie1+L delta 13924 zcmZ8|1yogC`ZwJj5+X=?N$FI&yG3b{l5UVVba!_nNC}7_ASoarNOw0#OXs(l`M+ys zzPn(-smo!XXaDNicQ_4xE)^b2RRIx+2o4Sn4sJ^>4od-hOD;t`zcMrl4+#zqulgN5 z0xE|f2M_p4h(!=b;gsc6;^0e|MtBa-@dX_b3;qco%~KmwXJbJV3u8xP6K7LLRuelH zTj!TF9PAtd37klJ2wQRqu}Dv$S;rY!JnzNN_S^H_MxUQ(@G|;Ih({tK(^U@4KILKm zGhF-L?A_AAD6QWlW(RfrMwoa?i_-b_D0V&7t2llS_#%Nmq0c_9`&qtN>}!rbo8CFj zDkAPwy3qWJbvL3#Fex3rtW#+_=?BT2p+D+;UuNA5^4}4rZ8S2zMryS5hZwq_)_>+% z6rNX1GJU1(-@hqjXRJ6^KAzmaK7G7`HU3?@wV~ltkz0KX3e4Qgr@VA`yS^0fNGr~p znu|eef?uSy+;p)yAu7&JeDv_mEWh=<-MlT)JF4P2(RU_JH4WBEO@C!g{|5ay=6P?h z;CT;iqP{#}HX@8{-h1*TdK9*46Wn;6ox)zTnnF~qlP4F^M-X+8xpi!}1-PzfY z5STXf{Y}y!&9}38>K`0K@{K}FmJuZjIl*a22;*ZYLh8vIX?j&f8I?L>Hl7!6(LxG; zrw++Ph(zgl^_ikEqn(>1%v*(cq@xpc33TDnq0YQI#??-D-B!+nm-A-$mt`9*Qkj5PE|IK%(jVk{o2$5GF( z`~mJMpLI;(l!I-?{hp^B+7eU-qBlRp0z?ZIivLGUc9fmIPCTKs?Y ze~1RMapfk!q{6&@V`Zqjy0M3+z7Q3C|FaVr+gOie+_trpMSqs)Xp>FeiQTaO{nKa8 ziUyGk-l$C7_=NdC-o8X4R^9q^Tv@5tFp|g5NQ5IlD=zp|PBoFU8o?&yYu}~h&JPmG z;HNg#4WHOE%5%$ao^?ShQ%YHoq$#M%Q!T^Qv5wfbU#KzN5ZP8~Zd9+L z`L2c1FZb9z?{$UD+&J<;-}frojDp?1zSyqZMvMZE)XpyB3u9hL5zCD0?J8SM7&jLB z)=v)15>AFxvsb8r5y|n`sJsS*p>LPpsXm2-D@v^77_Qnn+)A6*reox4eLwTNphV|d zyG)HUC&}`XQ0Y*x!iH5o$&4!6Qdg!buN?fIMqgK4m|gxBDAbZ@F;eNS<0D2MH@u}Z zMCq4L@QpudfY<2<$0^?& zb3Vbla{h3Wm=R;?8LUwGB!fZIZ1COlL)vS6o2NnuUn5pk2pjvgi{9J);81^mlrh7M zPEbd&knt)!;(!)Y#yJ_*MY-{cc=Id!*)T~e_``7^hy zAt%(8x+-DJ%o=FY#no zhFlxF5q&ouDZDNCLv-(!JNcwvZ-y>S+2mmsBgJ^%HlqDC6=fmrcqSE7TB%c9kj8bD z(@})T(j#WF7>TWc+SXEt{m>pi`B$64M-EsMo%rCbdKFg5MB%+-R?yS!;%XKmL$ zHhGTv$;x&lBk8~;?ruAqE#}!xJ)1^6lp$j6OYAD&PI6q9Z4*F6-4uf01fUP+r}|3; z$oTP&t_wSLLadUh{V)5>HY=#?TC0_H4RP;}qg9H>=n-R@)I?Kj^ahD;Vtg}t#a?(W zgd;t+XZb|IPJt(&y6+njSfm&5;5*iwreOr3B>I1V!o9zq*@cNS|7!fSB8D`O+v8feEDTJ~I zLyKN9T~YB(nz$(=e5d&sL#Uf57c||+DITEOINHK0+Y{7>#Z{5b4$t~*)TR=l^~Kz& zwY(rYG!y3E^nRsQ!rtypq7E9)tG?`+cLB31b=hB><$McM$`hG`l&w-Hn)%HN zv#=HO?p|x`67eRUpCc!(S1SPqS81W-YdM)5qF$sr;YY015GMSF*Idtv_j)t zscCetA@?*%{P_=+z`S z?}YXSr!zX!81zJWm9sw0Z--#W?Q7tAk8|7~Yx)mvh<5YSUK)4(`04RXk8ys;w$KxS z#jua)tED@%%#Bd~vj@vvO417D&q^Ww$EmIQYnypCR@C0kK+p4Ol6ievr#}R8Z{>u8 zMgq(`)6x7Pzb_dCag}Jn;_-&G9ojCN%SJ4{1)L{G&0VzX8q#evm|Ep-e+CoY?0yomZ)n(`GxcyRGxZ-*gjM2<0>fPMi>?p)L5~M z>(7kS@YtJ1gQj-sU6KcV`=D97eSBl81-qUW9*HnfaYdo2CEt5&yG^8qIJ~PG4#gw| z9LrGoF-svERPvy~uvNO6AEh-=hyOOSKp{zQpoV@&2`&}saqZoUF&X8+v=9WZm^lG6 zE`&`fNNUOuQ$cuKkd_h&zrc2cQbP3`6M@vMNFBAO3af2sB3?#Q`F+6CtG1{ln(Rlm zdR`Z^*JXAhKIfjlOdoM9+u~Le*@hZi?%3e>zv4PQqi+6~h*2g>LlUhj`@7e1L|`{Q z)J8Movi6jB^xpM!e*HkmZ*JCl!N7_?nvZkjG1M@@BuxDXNfOb_LR__N`3r)fWbD8| z@^E~qKwp|dom*5W^X{O@Ydqwodkh4L)rj~^;toe#$w&`6y&CaWxOCofKMEqwNf_gd zD}$3xLXb%3g-Gu=D#w-p_NlW^vy%mgwQW9%b@bTPpR;N6-&S-PQ`$7)3-_#*qgh;puz4sOk94 z#&o3jUcb^&%4R0&{ph|wN2Ov#vhLR}_5RRzp&jL&-J`!>JI4!)2(f6hqw{~deS7&r zg*RkV&I&CA{$vxn6MdF72-kIq81*T|ia`FzK>&~N_nUz!-C~2>`Kye*2|m}yxiKut z9n6qzO|$YDR-)RCtM6FG!9ezs*74#bjTCLEr>%-Op9pn}!={8SRu)KoRnpN8Swr6U z?GIPvu1STQ_uDv9%&%>sat_T=wNwS}k`E#LL=G$hhh*7&Pua7q*ba3(^DKQj^R8!OsPdvy z;*}fQr*n@}g@_2jcH4Jlg4r_i+w~4?m&a&MPuTftq;4e(JH!#aJHMesKAtWzfaqHt zd@BQ&RzjVy`CDyi23L~$>+;@xXBR4a)rS4rw1)lrd(#Egl7#tT!=XoMCC}AznBQ}Erx*Pu zS0M64#-w>9Du!)T0MibCn(KUYUeT0dK5$?_>hP^k>g@byIhXlaW}47uhSM3JTaHs- z>xWbME+ZoUV|s5ytY(zI0o14orjPIv&;%G0d@1pv#KYB|I9fF|wW!B@XNQNe8zNp8 zLw$XHZEd+#gp=j3xr{rI3=J2B-1euYrm)C3*H&Xhq+tkNDqkQFRC3@ zyK{W5wioa3&eOQeRR>sg>t1+W*r%}RC$s9FjlVL~s(6#+Dwb&SGdhYwfb-?cEXTp@ zmqM<)kWQws`CumYW8T!Xv?S(N`yD};y7jiFXJ==B|4MwgI9!%p+t?7~=QrXL5NHq! zK*`N2DxyzHPE3?E1Lp`r6j<1>UBijbhA}%~(b3t0E;|=Tt7^B+A5KfP%Ctjpo^(f& zNi;n-Y?*6?pto;VVnps_1++>v^F}8tblonY4O_fUwuYzltKW8w7ORNd-~8R(wPv!}_?7nV?Dl-|&%OXVMzFZg&2j&8_v;Ys z$H6v#CMq@uv;M5D1$sdcR2|WR=(4@B!Qj}2DCphpk8I&%JNIpQWyL?-&BaBEp-2rn zUqTHp(%03Ul}}>IE77iaqh{Fw46`paD*esW7js;C*ZsM$z3(1>hct7GMaje315g#* zcnDTb#>-xnjb--q_g`Ob=EO-m`8!`8uMeYz=?exXOAz^I2mK1a>?f1*v(2t4@szjN zl_x}=^DF$w^IqTN6;a2UyWJA%KrCW{1Q8LW+7knwS~Qi&-LEvRy_v60&d$Gjd*zgr zn!T@G$4j-W#!8Iey-Q3^HnX+OPEFMTgWJ~D*68wQqWrZ+ef^+2u4+e&udnaP$;r^r zP)|?K+S*zOF4fiLCE4T0v_~h~qhwrWfgvFW3(b$eJJ{Qk3OKH93}kE$WEB4qGXDu5-yh3ICI$-USr~_Y~qT(Y9HFKf*wZPm$Cu6_fc0LNo3Rre|vv(`L{2L zxs`*EQt`7vbFE5DbhPbIu9%;|VH_xpX)pp+RqPfe7{p9QRz^m?iu@85&AFu|G5!7h z0bH6DZ+MI+>TG7~uf|OY6tDk(n#pWN(2gY?u?Fy-=zx2L~6mNN!S4~0 znpjyyBv!0Yn32mU#AgF_goAwLLjXsSn1dv&4NvnPaX zgq;>~X6H=6r$n^_mwk2CuC=HZk8!m-N`g3i>0Mv3fiE`>dCc;Ukb;dKO5Np=c=$bW zfmOV8B+fqz%|aJ4md3b#O4LsgQE?<0_$LeH2=V>tJ7Aeiz;SRXLMCkAt+Borlgz ze@~p-es_vPMMZ@yAT}1y{nhE8NfLpJOCn`m`Mf}?=a9kowg6u^KUr!%JX=ODxflDn zxlfa3#NeryB=`jd-$y*T$O}RzqpQlOkd~C}?1~^!Gah0b5(c1+$9Sl?O=+K48Dxto zkGg+&cYA$*_2=^^jbicZB_>$=32d)7IwD{}WHemX6!r*i;f)&6WDsi7UK zp+)9JLXFPb{`us*)>|7JC@#UCp2uswnF3B#5l&sdx%v2H(t?A7ztIFfp0mmHw;I+u zM0C;Aphu*?xi}eBp%$VhJY+e1)X~(b5KtWOGyGZ5du3T!IQ^1?$wxwe_oDUN|Vp6pwxH( z8=ey0jWh9FgDq2OU~V9lJ8aE*#e5<@TQ5!F^ra$>0&RFtU|Ui-37wpFz^%=<5uIcRdXqeC{-n2TDphm zqsE$PC`=}k%~ABp-s9N2Km@Ir9ui1iCllsP)%iOyoB1v_K3U`6XtaSUf%6MDm?D)5 zOMqSEq4r{8V`BmBYL{wS&eU2S9Ubw!ACpy3=guYg zsX6*lDJm+8kdUxUyCPh}cD_-o-gf@_{DANM7>t=YqR+3WsAzo|`VrzVwy>};H%Gw> zW2L7@MuAm`2Vuad1qI13@qT~n1l-50U9QvMxW2abj+vQRUnHLs8_-jg@sF9WR$`$7 zP8+!&o+7yI%}6=9l)wJ+(QdItmfLcKj-Q`2L^QP7^F03;0lW|qTd((ps@5+5Zl2_A zi`-wvfLC4~lm|mihQTu(9j*Sny*@XrwHO9`XEu;d{OA#{=b3e)>rxwh;?lvv{h!aR zgE=Bp<{qA&_ki`jl|56*wq9(R|Mg38Gv?DTadeULiV8p!bGc#xV`F1CH(qo@Mx2tZ6iLCHm;kh%lN7rVW)Gt=UI4S?L^!-w?r^qmXzBpcW=s=)`0I#PC{wz5~B z4=eA_X6>9UfOzS^I^gzZAdu18Nh`AN8~dc;0Azq(%{z4OiNxf9j|eGn`X5fYcBC#> zt{IYY)uAwgl-zzfkuFYWgrK`m(t#iRV2811B)<^)+u1z0)F0cJMA>~-#K{Usu%P6I z^qXAC$jDxL92cq;Nbk+ot0*h;^6)4rDHT;DC24^Yc=P5>5|dUH4=-<}Y94~rzHEVy z1%o1aFnWj{Z^{*>oA{0=ms>dhZqfGjyVaV8{8 z0L5-IQyaEXFS+OXXTs+1#sE6_|Fj^! z6ECcU3cp*dTAbokqh@IRhQ0Jf`)C8bVDE#C)&B}a|s0lZ@lDTjF5+9jX)`@m-* zyDry~m%zuwqcm{I3xPp^!Ahhe9vxD(gA<2X3Z$bNy|3#cBKm7g`)BHGFb!+oe0{(5 z+S#Wm@*Io)1`_@2E8Q_Pgm;VPyd6REd@xfWAevTKxW%+T*NhK!_eoFeoy`xNuYGsSq^k(?C3=b<}}m$P<@;GYQWhu=BDQ61--+AxVX4(&d!Mq z6s!pCT=>aoi7%YTVBd!`Gcy6P&Nq9KWQR002{l5*y1Kd-^zVG7*B_|UZyoT;>{lxi z0)mz8ZS-rPTsGI&+hzO?{GG+c5snZmaOyz0ba!_zA>kAi7mv~p1-;hQebDr9LtBe3Igl3LYjvNDQXs-v$DBO1*co7N}SK&>eeQ3W~aYNg+T5fi zebTLGLkp2$|IuKfR+xpBP*9j_@8jc$ zGjvff$?tJYcSWxGV&VERpY6~LIe#EVFh?eqJL#68MYi0IaL+Q_-9qx7-~?BuJs@G&UJ~y&`fLK@Sx}P4iNW_sDHuFKQ%o~rX*!; z&GLb)1Z&wKRxs#yp87fTd@86YCxd%MOu}AL|@u(wnS! zjww6>0tB`2!JysgUYL~XJ`@^L7~8ZZRJb2hn_;hkh#t?y)m5;L5*dzTVCdxQo2ExmGn_zHo7Iv9hq_`q=@hZ1wTJsQUEjQ*v_h zbA#_wE#96Pyf&c3q^w5o@2(GOJD^KISYX1XBqbqlGSJc@$`~uIZ(Yc6g#&Qt`Tbkw z)(;h+K+A{I_xAROpgv=Ty)LRUGBV1_m`mp-CR`W3djRkIy1~&@S$PnU!@#d!($N$R z;QW%6uU3;YQ&YS1O_M`Ihk%_lcY70_iE+}>765S=izwspC_knu}^Wvs^ z`QZdkO>^fnqe3#v_H6z05e5bZHa4~;iYLVDhfA~Z{_&f4^KOglzz*C=128ZSf@8&( zsWt|4^hXFT^!!!j9B_i0ttQuV;2-y*p*OZ-Dn0Qz`UMs zk5B4gD5pP4DviVAJ^soTnMOg6XWjV`-Cbm4GAcxC2z2_U9V% zbtnZK3qiPmP0l?e?7TO_16$EM(Rym82Iv0-43*yYimtIvd@AbRGzZB7V1h zz0frvLvktH*-K7a@9&zNHV1*2B7COYshY@MI>!ryz+&@0Ow` z7^^?kH8k>gmWuvuwVYWbpDX#!}ij- zE?S%`YG`Qaz{Z3NrST(ggSn}Wo;wIMR@>t^#C0z)R;t*q^4fV|sB;+D*vKJmq;q?# zKVuw9l(PhTkfc^tSH)f@MjlhQ4paD_@FRuuS&m4i;C@S#Ko?PkPNWoyvS$%RtyIFU zPXCw)c^to6ewDA?^Q_3SuRDe+W-pb)MDw$^7U?RUfhiQvHBvo4k~UD{Mc1M#kuE_P z(iX{3NycYO;VMT=sQ*zpOP;nSP%}7+^rw`XJvZu$%F12f>i|1{8)0-rt}X5uS5|N< z@|W`Qu-;>qmoczZ>|`F$v}B}xzo}`bu4Rf>Zul?V3(TC(>(@M16N;e-@mR=A5nEdp zefSW1Qt}(W2#nuLQ4#K;WO$ev7-|@4)B>C#oqA!;=-Gm5z0Zr0UoMS`S>*l*Hlpq| zGBU!$$HylkDva-m`nO5OXcVO&=Xl!*;)p!$V4Np{Kp9T~p|TEgmJ*b)pPP6*p)q1q~0|vs=EAB#)O!P-+v!>J_tuhlfAR*}_xeg7@S| zqX~^z3@U(yo9PA`ff>`CS0mt=-*Im^r2AR7ez3O}Jqfj4{O(DV7d&gBBjTkv=MZ&L z`b&G_Ja$WA{VHk|Y*;#go8fm7C+h|#Y|Q*g_TpkG9UC?ImiU&kI7+;rbd}wr9qk_* zp*+dAWT@(TJtPm(8;Mc(qZKK<(8{FLRJ8D+7ZIjTXOi?cslwiZbs#7pCYC#BBof!# zU1-jjF(-I}v_?n0cjZy* z)NaPZRCi@Z{V8UO6U7qse@CbhJ@^?TANK!1GoZ~*fw}|+rM{jXc5d!peSP^VXd_c6 zwYA)6vKks1H6+X1+S=MvBViQTm74%Fpy7N-s=B&*Nk&~gzNx9Hwe>*(d~a?ps@`7o z`a2Lw#?^)!t_m(QFfhP;#L^a)s|l>Izzh8xph_(s`&=xC07TXJb_w#oSW$1Q&W{Dg zxpwG8c|O-?HlCiIQw92d*aW%JAUX;u{==21`3nfDu1A>{z+Z1Gq)1ygLZLFnXr~9Q z_Xde@j-hBScMAGBYI7v@ZT3<5ngY}80w)x6Ra|Spg`(n8?v8yL1-_?fd1C}-pN8jz z9h!@`cX3LC64bL4#caa4fJT4geskfVr$ z_$frHGXP`uuNbGAArK&Su+Y;7txPgLHDG`tiKFk^bcGYY0>KkVfj}xn`uOpyO1 zuBc#*QjSIOpKEks=H@;DGelMJ^1bR>2pUFSC>}oEXDA*UgE~8}iyTBtQ$woQ4xY6* zW;!~g-#iZ%USbf!({?qQMdkxs`KXi;yay6BRoxO1+1I7KmZ1&o9~DoCN)CWHjF%|2 zVMO5R%Gw}i5H(veor^)z7@aL8*3~^d&YClN~?_eq+R~D~s z5M8z<_%dzJHE>0OAk?oCgAD;gjC`Gl0rIfl|1ENlB@DuC;*h104jzM6pO`SgUJOSLuDUE z?O*4Dh&>U;zLm)-W#MTYFXQ>1I_loH&+%Ks;Qs}op)oN(g_!>SM$>~&`jGA#^@~$D z`75`$oQ;@bez7lIUeVYxB_t>y&|ZzlT$T{a!NXIO2@FF!$uMPq-yfxIk;Fqp>u=86 z1aI)KCK1V#wDSm=%YJrsflMA7DW9T5NtP6b8C6~0cuODY22X!eqTj?TNV27aHn{ma zN8|G_U|3mPg5>@E{V8$7ArV?`$>gh)nimiEfG+Y>#`9#$;V-nIBqQ_l@X#JZt`)i$ zZp3n?2ioD)X9L!9NG$z2MI9;V{-7X3bbhhP?Kua>@Z@AYbbohJFQgO!XMcZeEQ&57 z9YcwY0@O9NezEeCT5R(Bs?l0B@>|R&D|bcCV(21o-@diBwq8;kvNitlQq4Ulc!J)s zYJ!zjRb2ue9)h2mnVlUSd(q^&moDJMaD}tGvA!PGkWN5A&=%9yCMuf&kBAa`Qna0` z^C$Tc2npUq09v`ezLw~_y0|bRxkVFr#4peFg4)K`76%nMq-Rg{Q_%qsmD41QQotI5 zkh9F-K8@3UsSR{KsEw_xm^&^cWpm{Ba!>Z>bs>Hje}s3OI?|IHk>a@6m@{VUE8Sop z|Cf^g35{UOr%E2k8ZTwgKil;&r|t;IyL)RGv}^uW>-dv#jPdb9G=ah52`$*u+Fl_j zfg^v>zW7q%`GV`a*p9ORHmB_o`is)oPoSUE$)-0<<#QqSUK%kuTxWv{x`E)KiG_vi z?p`?u09@%4@QvirRa4%~-^T}FC~Vb6?f&2-wQIcj7xWz+9Yi;QZ^hdq^vmy%2R8ti zK)0upAW$(gH4O?00sR>Yc}c7~A7)8O$)Opx!NI||Gr2(cU0z&VTwMW$2E;Hw$O5?m z*bISK{wUEw4brRT7ZKb1=6*zD%fiX&*q_Y$tvQ^S`7N{dXMY(gJUl!Sl2?Grfrl#@ z)60V!00I0XQ|Zd{$hSv`g6ne)PM|$>wU(fgtClBosQ3N*_rxR=abKj^pYG8>F@-n+ z3$h0SZ}2!lIC`-=&GkY?HL#`SDWS?E6_IDpppfM3F~YeP?l1|SsAytQi zu)s>9uC$Lb5H|;(l(L=fn8_oD7a5Wk zVIJtVvJ1Qa!@;?+R6s;NSQ8K`bh6rjw#+jW;PAXJ*HgT&&rZ+Jiwl6J<>BG!Vg#66 zQ(s?fIzoM=p$@5+0-7j7akccYuBoo7vH-0Saq$koa;R9Os+nO^WZ`+SR3HbCA-0{Z zs{rs&t0XUvfs6aQr{@9;J80S&=7}SZ)mB|zAGFFukt0`Mf#w}B11g#PM}VBUMLz_wvLTbwnxV!GTl;C(dMgdNg;ngFR#`7u@pLK%(r`oX&UU9k<+1=b z1zKBD>~TA%bAh#B7M^U=ws3_jurF{C9ZUS;EMd~qQm{dj9SsqWdX2*KHlp*V9M^h4mqA8K3iO%AOVn0DTGiX% z&&9`g06bEw&utqMX}L}{gi!46;n8kTFA}4s2wRf@{m0eS)iSLzhC1#}u_A*f-CbSl zJL6?fk)j&Dx?{`8$Z)fR)*;iYN(xpkDHLan0q33}W-z#5K3mFjY-<-8$VFoXV?X}* z;pK*FZ#?}Zh5B}g^I`Y1ieGL>c zP&?F<$7g%9Ag%laYRAtkcX+)&1se-1n(`&k_9Y-GelwgWdFaz^{)cN}@&38n{v5SW zXIIyFg>F5&51g^FF(HE@sgP@VL&IgETtcFLw3@o=-EF|fJ2?df1!d*rYHkjW29LiV ztE(Z0FJ=S4GK>|gP?^4ZmxxAmY_inmH>Nkb_J@;H&>8lIe4Er(no+!Z1v3Jn`S{(x zrr?5&SFAxp;0G5jdjIpy9MD^dhcG-=c6aAMtFVK`+so_f{D2B%csn~xoCO61r}k__ z!Mx#Rh88^U$b58kbdWy90by_cs2c(?h;E&AT1be@hYx~S(vhTjhYMr}lwIS`A%Gbw zBDZuV(?Ar1rhIFz8nDK{GX)Td1L~eJFa&pN)=1=Tx^G?~=gMIlM+yfqsP8N^H-$HM zjlfMj#}cUWVU&Q8-L9;x(D?tXtp;s6==P5xsGk0wo|0Fe7m5^86d^^$H}$qp@bQgJ zO|^>TiBVBeP0!ohabcA{pa&5Z8JV~Ydba~0Eq`lb;^gQE93=?_MP^o(jk!4qDQW0D zn9l4XCuHD$ajAqQJ)fGOzoDa}^Tp#E2Nt04-U`4z2t2hw%4y2i<}L!>SM2dqD%z>C zSI^_56GowL4kq#dxtVPt6Tm90H=kCQT@$(;tAx16Y<>dt$nYsEr z-R92%aTx$wQj$7KKSY-Q9sM_SYUlM@Qct zDZ(7|hhun5A&w9;HJ*qOm?!|zKJ|SZ09y-Wgy} ziPTs)=*$3YOG%joY99>c&CSi5S_^pPr^`!A_J>Pi6xe8JkiCP0-vCI{0bHtqv`hzd z2iw{P2C!2G2L|S=j3s~;w|xqOpRuPa>QgCu`$jQr#3k7~TtZZs*>_Azkr4j&1p7eZyX}&@Mc4&C`4(KV9 zElFZxVyf-{I|ZwXi39ogk4vfrVyfjIN9=a@;RBfjGt;7rDEb-;H6wHad66&g%j5NOqiTO41T}R_@l05Zw9pH7(snFjJOIkl zQ9YJ`y_YIk$Mtm!<&!5-4~dMTj~A~!pmgA>G6h}U_a!nWLWo}c6HB`+% z0jRj(X`Oc;O}DqVg8&E%17oJzLy_rvK5siGz7oF^!NA2wMFK3YOOoeTA(9g$zQpT*u?^JzVRm}uRfl{sa-wmanhb1}L{0<$U zX+JWezJ1HJ!20j=n}GM%FhVS}1~t~H0A^RjBi3APLFX+za&pil(Xtl9H?41Xp9Ba~ zR6$-vA>#9*j?N%gduV&;L&;kn@nFi8tUn~pSFMSs{j)&Q_kF{FX)M)cC7kgKfptk} zv?2G1o&3_8O&`MNAC`N|NhwQKiW~X=_e$^tO#vnFS)DHh0x#hoKC=@eM3b;3hn0XQ zg!ZsWE+q8NUT=9UjQ@OS2%O0KaKz>XO#-$8#(y8V72^NrNY?)zv3bG$aHQac7Wnby z>P0pB!_Nw7`+xmuDp~IT{Txz)kt`$huvmRI_CL$mvHok}IviX8_`H&nsk5`Ct+~^~ z+I3Y0cmyIiBDjB+x&QZSvWI2v|9P=t{LiBIe=hw07n>11tT-e6&t>4ZA%X-7IffSx zH`e%9_=p(ndIY}z_r^x~;oz)|J?vbZSxt;hEKL7-|9{_Df{z>pJWWD|+~bGwP?D!W zFcwS@Qy@&(mLmpx;=ztI!30Wq*8e-4FeXQo;4S~?pG^vRqJ*x0Z_dk8z)L4w$v>m| z|CjYs{Lfu`C5S38KU@zkK&TT+h)`hoXKPm|Vff!$mkJNJ^+@qwk5*Zc0^TFRN|Eg8 n!#l@zh##`T!@=c&5r6oX|MOyzPH2`UNoZ2UL&=nR*!}+iW0rs) diff --git a/include/__init__.py b/include/__init__.py new file mode 100644 index 0000000..174e139 --- /dev/null +++ b/include/__init__.py @@ -0,0 +1,2 @@ +from .argparser import argparser +from .content import content diff --git a/include/argparser.py b/include/argparser.py new file mode 100644 index 0000000..517ebf6 --- /dev/null +++ b/include/argparser.py @@ -0,0 +1,78 @@ +# includes/argparser.py +# +# module version: 1.0.20130424 +# + + +class argparser: + + def parse(program_version, protocol_version): + import argparse + + parser = argparse.ArgumentParser( + description = "The server side of the "\ + "aliased server remote control", + add_help = False) + + + parser.add_argument( + "--help", + action = "help", + help = "show this help message and exit") + + parser.add_argument( + "--version", + action = "version", + version = "Server version: " + program_version +\ + " / Protocol version: " + protocol_version) + + grp_pid_file_failure = parser.add_mutually_exclusive_group() + grp_pid_file_failure.add_argument( + "-n", + "--delete-pid-file", + action = "store_true", + help = "deletes the pid file and starts the server") + + grp_pid_file_failure.add_argument( + "-m", + "--allow-multiple-instances", + action = "store_true", + help = "ignores the pid file and starts the server. "\ + "Will not create another pid file.") + + parser.add_argument( + "-v", + "--verbosity", + type = int, + choices = range(0, 4), + # default = -1, + help = "increase output verbosity. Can be from 0 "\ + "(only default output) to 3 (debug messages).") + + parser.add_argument( + "-h", + "--host", + # default = -1, + help = "IP or hostname (use 0.0.0.0 for all interfaces) on which "\ + "the server should listen") + + parser.add_argument( + "-p", + "--port", + # default = -1, + help = "the port on which the server should listen") + + parser.add_argument( + "-t", + "--timeout", + # default = -1, + help = "timeout of a connection in seconds - still "\ + "doesn't work obviously...") + + parser.add_argument( + "-e", + "--encoding", + # default = -1, + help = "encoding to be used when communicating with clients") + + return parser.parse_args() diff --git a/include/content.py b/include/content.py new file mode 100644 index 0000000..79a4545 --- /dev/null +++ b/include/content.py @@ -0,0 +1,78 @@ +# includes/content.py +# +# module version: 0.0.20130424 +# + + +class content: + + # handler the content + def handler(client_address, data, aliases, server_version, protocol_version, verbosity): + ret = "" + + ret = ret +\ + "{BEGIN}\n"\ + "asrcp" + protocol_version + "\n" + + # Look if the received message is an + # valid alias or a predefined command + + # if it's 'version', return the server and protocol version + if data == "version": + + if verbosity >= 2: print("Got valid service command from" + + str(client_address) + ": ", data) + + ret = ret +\ + "202 Valid Service Command\n"\ + "002 Version\n"\ + "ServerVersion:" + server_version + "\n"\ + "ProtocolVersion:" + protocol_version + "\n" + + # if it's 'help', give a little help + elif data == 'help': + + if verbosity >= 2: print("Got valid command from" + + str(client_address) + ": ", data) + + # send status code + ret = ret + "202 Valid Service Command\n\n" + + # send the list of aliases + ret = ret + "Aviable aliases:\n" + for i in aliases.keys(): + ret = ret + str(i) + "\n" + + # if it's a valid userdefined command + elif data in aliases: + + # send status code + ret = ret + "201 Valid Command\n\n" + + # ohmagawd! a debug message!!1! + if verbosity >= 2: print("Got valid command from" + + str(client_address) + ": ", data) + + # execute the aliased command + g_dict, l_dict = {}, {} + exec(str(aliases[data]), g_dict, l_dict) + + # send may contain data to send to the client + if l_dict["send"]: + content = str(l_dict["send"]).replace('{', '\{') + content = content.replace('}', '\}') + + ret = ret + content + "\n" + + # ALL IS LOST!!1! this has to be invalid! + else: + + # send status code + ret = ret + "203 Invalid Command\n" + + if verbosity >= 2: print("Got invalid command from", + str(client_address), ": ", data) + + ret = ret + "{END}\n" + + return ret \ No newline at end of file