From 0154c2d689628ecdc7ae5512b45ebf52384486cc Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Fri, 17 Feb 2017 17:27:38 -0800 Subject: [PATCH 01/12] update docs/pybullet_quickstartguide.pdf from online version https://docs.google.com/document/d/10sXEhzFRSnvFcl3XxNGhnD4N2SedqwdAvK3dsihxVUA --- docs/pybullet_quickstartguide.pdf | Bin 428975 -> 480900 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/pybullet_quickstartguide.pdf b/docs/pybullet_quickstartguide.pdf index 56cdb8af6f15c9020c28e74d2844aedd4e0d23fc..418a9beb82452826e3df51874f6fc992276b7ece 100644 GIT binary patch delta 195151 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

Uf?$4sGBXiqNJY|2iz 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%0D! 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 delta 143147 zcmZ^}1ymeCw=ImjLvR_~-QC^Y-Q8UV3+{u3;2wgzy9Nku!QEYh{^Wl5uJzV?|D82! zcb{GRRGm6i-P2uD;Z;O68TjawDiTtRtW2B;ls%7y?+DzS$>@aaY&^W&oB(DSfIfhS zixt4e!wE11Fe?MNc>&Cl03KEjUJd}W5`g^^H2@rJJZzj?$tJ$wT*-fYft&z#?tf}o zCo5+F4-bF^pax)8b9VLsaC861P`CB71hBHQ0hm?XEWQ5Y&kgv$KFqQb0DS=-b_)wr zGj=m>7E@jh3s!DUZY~ZM7IrREQ*$#5ZZ1=y|3`uLe@j3+;N+|{h-8y`A{0GrQE|G+ zWZ$SDWQWO+YqKEGXnBbyw5(0cUV&Ed%TO@GeIgKGMR0H(ATEe~ivJ4O*~|_>Kmfoj zVd?JS{uwswe>$OJYHjHb;Nb-cLlQ%9^JI|z0tcY01K9rMO~KO1+QSCG#=;3og2V^% z_W}mNpiQ{gArX_tZbCysAj#-@d$-)P8T~{5z&|)xp+q`Dn5i%S45rHN%s=S$%^BP4 z9fWAY%!bWW;+==3(RI0Er{$ecoL(DX8nZZ=#>zikxC*sx5kG`%15*+`;DVutoOzpR zTXH&d>d5gwzrbF)ONU!Zul@A}4F*?zGPGe@g)a`_r;DOEPzg z2oV4mZRmv(M1^GI=19T%4av&M37WyGqGomQ_GR<+_VTr2w*xRs0Y0aQnx(nN=S<>d z0kCm$0$8~?0Bl?!RXkCe|6ThpjsL`KpA+amVo=Z*VtDpXi{oDj2%JXrlfh5Hh6XKS z%Yl@!i4oY?0IZyB05*0`PyvF-C-q;YWjJym01h!c%cmO`JAjS#U(25iK8X1X^nbBD zy#K@M;u6DsTCBXEQyvt;AO`v*U_K*Z8WcmU400jHNBmdJ#lsEY;9&*5 z6H9z@#2^zAdC&?m3Cw3~9IU*cX%dM~6Tg88P>e&v>c{D6>Fs9k;%fdm$^Xxx{Z|t! zD-VG4-x#oiz)3`r{!cMzh7%M1Uoi*ke-~4`+nHI|+Htvyy;P~tkD=Wwp zL-c>waOQfS0JDPq`9^IzjBG!z;6PcTT} zJQ?Wj5Ht|HEEzNB;8ftO88aA=*jQ};xwNHNKa=_2r)(L?Yv7s?JS-X4AP5>DCkGcm zNC@G-F9)CObHmkyy=L^lyqcp!uyo%ZFwx-LhlD&#h9p!OGgwi=-rpaP+c_HYl=U=| z7sDM!an_}jY8DGW{8h!B2j5;2+COZ^oq#X<`%5?<(S-~FSF6HC@6VB|z_qg2^zDt; z^>sPt_f6xV&LNVZm%sbK7m~5_!;c6&Bu#F);v4l>4WaE>jJo&ouCa=%WX<9Y@mI_p z)C>3;6608EU8%gXmSDfbYzHhzgHPa=rFt#XVp<)9_v18J~!dT9fC$9?= z_{7r)S*_Rs+0PpGW8s3ETU>8J(0MY@w#RY8Vxrcoeo~HR(=fE?mv`JKN6a^gaDRh{ z;^dPFbYhnq63V`BpIAI++tMdRq_wG!Mt7)~F4Wt^4X~^P>5i zLEK_`%PN3Fxel$wIq1oe)u>pjM|%uHrk%S5v`-_!#>8E_=v*bxfMTw&24%=F6K7k) z(CI@WJPTgGJ_^A3=2-+aDQ|(U8uAO?R~cfufKD?&Rf`qakkyj1Ae;n`T}-nf#ovyo z^YrfSlM0ng`ISPJRaVVIN=_`R(gtBR{oath+hDUKeifex#3s8)A4r@wAG1N=&=sT- z99|z%$8{?8U_(O+dOa$>Nr`g`;k_ZO)`MRn zlMxYb?MV)tYqI8_rxrCFg@QlX!ozTxS>B9Wikq8Qcc7IxXyj`r>3OS%tGHTa4zq5) zBrGZ(*4VfEyzNGJDC$211Gk!~R$-^D%kmpIH&Aj{^gNX@^547!VB1zp)fxM+*^2I9?Cis+3-F)zOEmo4pd+NzrZ+P0HgtA7jvB z8%hIS^t0mG!Ic)JmeB7^sA$y@{gOi9tY>J^5GV~Qtk$V4f@?9XOC!jrL>;NWbDW=# zEaHQdZa|b)i$*V=5Wn(Fb&&;s9{nR3T8WwptHx?Z%di?~Mmw?Ehl!P5?1_Ys=EFf0 zQePZmQ@YoUBLGqQ+zZe08N9w_spblv0xfU?9(&F)`Lz8!|MzAzk|pci7iAc){x%nk z`m(5cf=rnKca4meoxkT6d6FVSCG1vRUQ^;uM?K43mw5emi(q{z*yloci!(v$Xn16aP;xBv6d(sihTqr zj+&Cowg`^8KWVN)_241u;WAimWU4^FYh^B0POX>rAV{lF+ucrY!g)RV24teLFsdmJ z*TXrx)6>?|tMYNYhggm=?}vc&$&`c3qGphD$U8fF!O2ha?G=3-y2a=d%T`!6i!PSm zd;Qm&l%M`c=XiuZMqs_{`R3SxLPio(nFA+Ps5w!y>bd>#V>(T-`}XY6+4=Jy22q-y zJ><$y$wY>C=lN6fzfIXEAu%`8xM5{JKHIwb4C|It7T#@7Iv^g>RUDhv~U z2j>}dE!01mNYWB}u5V-!Fyn31a6qUxTZOF0$3UangfzWD>PK?Kve9~Rd;q3Vt8#`S z^e^%75zL8V%#ND+PXgOShPdXa9);quhtWJv6|EBD-d?9RG&D}oyJksb?rzq(brErdC#NU z?W@5kB41LwYwds*dtRR7l)aAGDTr$kYd1S!JN95+(c_wr~I{{~@Gu3RwYhplbG&Kdl_e-=v9tX&}6E{m> z6TU0F%6n6o&3Jw+K-`i47|9|xfi56y;zg{~BUinNMZ8fjrv>T&l98(w=N+sN%LT;J zC!&nKMmg%O8GqVb0gjJR>jwTTSB|Bc3b~S|pmA%G6UG*ZU*JH&?BNwrsrb-xx5uPFKZ2Ezrfua#2GBeX5n(kB&}&nHjP+W4b`4= zdX6e`*w|eJ77T_x%+9(gnu3v|5UNixLvuO}HSjEFlXTyTq$!Xm;GIiaZ-nH8IWupA z$}ST#&s1iuiBJ#b7T3GydGjk`%1|z0RdCKGz#I7IMwJJnIFejLkZz~^bF|2tgydZZ z-=mB7xMjNNi+#pL(A3IfoTK*s?p+VT{qPI8URTyG!t|_>WE#pUC@7cw{t(uD+^K{+=(Ar2S%anBRAZmiSz~LyvdUkc&!777wr?oVm9P zrn{no?p=x9H8YS_kua{}G>+8y`iIsvBa-P#M@wfn>#~YouSTb?GwRZo3E)C&?&L-0DRR@iJ}tG1E~^6iw(M zyXB!gzK|Z`UD9cJ8A9b>$;FH<%}erv9J|QISGdR_wD3@GX_oF?MgO9n{dh=dK>&t} zM@DSHHCdAG%9e&%urGt(X_R$-xtxSpI2^JfYFar2y))#C$OSq%J46I`l5$3=3 zXW4B8_^N807o_4gS2adrF8)9lW1jCD`}1BTB-$^2kEp@3IH(PqL!j;1A}Dk#w`Os z!2(O2%Iw!sR^q_8XoCxV9fB+t#8zASJ)5T4=ki~`4~wIokNHS8n2v&Y9U-u+f7!OD z&vjd=WZSlgg6A)eg1NJ}<|_j8ek333k-t=cv)J}@4-V|D{w7*OG{l-?WU>;m96<>$ z>e#U=fS%qDXAU6U=+4T(xx&W7p%uydJq>bRgV*8Qf8)pz+8*HECEgbV3YUMq?Xx*T zYdo)vgD40SE-|CpRKhAy-`Ho*aQYi}a_Ih8xb0tk^~U+6{Zk{t2)+)O!!3k-=%~QU zG`cm=VS*1+*%m_UIEo4b`Ejvniys6H{R$V*guR{|_xr7gouZ`2qd_PC#e(cS!dX|? z3z`K!F=n3L@^HddS6vC<#lZ4vXJiq}jAW`w#CH0Tm0*k3~w-480O8OsEPJ2FGM z-iW4%k;7@nBznAYFie724XQRScoxP6CNM_Wk+lo z8oIEa{5xW3;UF@WN(2;(>C9HQkqfx0imIsS{;zwoLRqT~bwNz1>PMleTmPU-;mb(8 z?!bzlC-ZJ6+3IEOATTJfI~8Pzy}0&3iG^08Ky8RYBJe0(R=Z)2sm(-zJ0TIEDp~NF zufsy?Y97WrF=7%gu}G)Wnq$MT71b0x7*Yq=^zrv=bE&u>?~-oJ=2n~;TLG(OqlWJI zWA~`}>lWpX+lLc^4;T?X$ic-mF57uHvp@Y{e#pZw)=ng@)@h>7L+yhh_k!MWt$`E% zm|`PfTI4Cu+KPDU_l<8GJi%T-QLu5x-Vr6?SKGE+1`;QxSIymdun&QIM^lV4{+cSm zs}Yh(#`N5*WF75TfE{$_FGKOS{0`{%CvuM7S@ta8HM!LlVdp!7n%t~3I1 zmWeXZEGdWP#*gL%LJBnluOlUswfJ-Pb)DHunzV-`2utR^1Pa15D9Dlf`v7xdlXmFa z^Uu3rz=X_P?Z*!XyC)=IX+!O~kWM$;F|J7k2`g3RQ+Q01ko*7{9mi&w^KG@qI9ELz<+H(=aoTHy(#Q83)=Y*UVI^Z_zPTVC>P= zpPp(z9GKh<9ydpU)6=&)k30|R{UL$vnp}Wv;sJWyePIn^lJn& zVG?nA4Z&D3M|*ZS5BH}$8FMtILD;ATgH5!wsL!{|mnGA{oQj%qb_4FVAeVKtO*KzX zG!lOclnO?M*gq5Jqd?65=+UI+{z+8}6GNuFWCQEAuEu8Iq-X4@C%vZUvsU%v9;}dZ zwR*;M!cfgmukI!_CY);fHR3i!3EN{zcSp>o zWUkS?$`ig5GkV9gAxS?l;vud`xu2@a!0@0m_ao{~)VD!h8Is<=oF>G-BZxP-FE?7)pU?s9y(o@?cvPM}<=e!^_glf*1?&lS|-}nzHm|y9A&Z zFfJUUWEDc}C7^F~$+7BqR8*9LCP>H(%bwRYm*0WbBm5dKLtP;+)}BBS zl6W2BnWd|5vCn@|Dy7>CHHB-Y=PK#%)VtM~Yl;J$x8Dud^{16w3CHyhr{2gPUDu@D zghzmn-HXrKv+_?QQk&O5P9lYaO;tO7OY8ya>*Bjqh3louQS-zJ1StavH^_0mKEho_ zJj$H*6YT2`ILq_*pSo^*!+D$^j$+<@m~YQ;F?gQ72B?ODv>=Q(kmo9hf>+Q`gDN`3)H{$ao)qGlrJEz3xjWWJ<+nI0|*6x zs=k$~mNVtQj!ZQpRk1r2k1;tnz^>sIH^JOF_B zUg{EzqWu<$b`f0%Vn_3hYM-vSk_bbWR1*FrFy;99bw&(#4rOqlJaLqIae&1YYgo6% zgkN=9X|(98nk`;w!+^f8U{fNZDL?FY=r+1dN|lj62to&COnA2gG^_rgX(eKH>xf!m zF>%Nvx8>0Cf;@A=4LJ8Pd?c+!ab`D+I-wYx{1&+uau^Y2t_%jLR5IM}h{^!R*gM!k z(m}sLqrpvGX`NulOKH84DQLnw%R57vx>sG0sPY$JVpwxuW-aoo{TnqPaXmVS2X;Ri z%}Rte(jrv09)@bhnI-R~nEv9r^A_$q)Y!*@&pUk*WKz*D7Kr^>-sWmpwHF}d2vY&E z(oFZCo43C}{^1W=m%u~P;U70OAzl?IIbwgu^C|tevE2yoodwr=(YtCi_Wwft3G~Qe z0oG*!fkV#))gBlyp>CE!rI-6QT|I7wA3yyayjM$X7Q(bf+i+t6%NaT(uKR))u!y`A z)#i@#FT8|Rk2o)H-ndABO7nFz!hxwX5J=m?eo4;MJgII<&!^oeLF1o`SW%$+R|Oy%<{5v^p?udHK%F}NQ9Uk_!jv?SZ_^S3_+GE6hNG7 z?48Mv)j(I~fxz&uFVTst8*pZo&m6g|n_>H4jIrQZ50D(F(!$|oCkHqz&Tyr3N$-%` zy`AtfuH1HFjP_EFNP(eGV5$QcTfc1#jt5_I(KpiLXC7YBgML54O7Sb^ki9C#q9vL> zJHyS_mo6mh2iZXrSQU zc8$A^tsDyHy6VwZA6}|vi@#2!hwHPHrY`W{o9l8O99)~HR$M=ja^_OZSOa6|_UqUa zjeXB1cD0L7lbO&^w|q+bkzcc?M!r@sOC*=$L)pOY5S4mZ_BQ4`vFp6!V)5+?aV1t# zpe9kvCJ~aG>M3m&UQRPZk->#(UBSD5E$M&j2la1ehTL0oH*BAYKEU~B3r?Oa6F=bb zGjc`ML<>h9QiP=f+Dhz;Lx8hYv*)uGw$+U)dh~+ig3OMfjSLjo9%^Qp_jU7!LEjWX z+FTB0e&vL+utR+1g0i1wk=7~JxrcaDR8v|tNAcHxx@b2zocS+JE*Uo>yQWH}v1o^~ z&E%uyT}xWk+0-FuyVRwMNu;jL(X>rw$T}rGQe9TWrZg1pWz&wSj%k+0X;B{j ztLJiR_rQ z-q>g>sqTKu$Y`kQwqW398kFnDLnyyl@)CY_#riCy7mmky1I`9olPl#|+IoYkZYU6; zp-;v8)w{ROLSWVF$U^KCTs>*bL1Hho{AzT2eUO-idX+VKnzh8`>==a6gUU5!pSv00 zd>ej%0=B6I765c-xY77{f*2ey-t-7~zuxQ#x_DCP^oOrQsJna0t|*mnnkJMDEE4*_}q%HLfX9|ZgeSlJ$*H}6Wg7tr#l+|nsCCra2S z92ZD;W7yU?V|BZ`lm-g;og9r7ZMsw!ITHu&AB{`bWdMtu2?HOFnu`Pzz4-M4IPPtJ zsb0=lXcwKLE-j^Ju+IAHZqNub)nt%>NYa+Z?DxI*aQ3M8kz0W|>FqJ&l4w${tCTrR zKxNUM*sc1P1|O@KpzxV15+O0+g6GZDN|CLN{^z=oN{r)CdHHKXIG-T(>r0`^)G*|@ zjr$knU0`b{d%UHALfQLBRy$DNZNRbxLIC;JG{gn5GUU>Pv@+Q8ibnu-$|R~5Ysim8 z0M2@woE(m zryo^zD8Filb)O*%?ENdH55_^CL3xD#7VHx|{wV$pT!922E@~QT(t=S}nwTg|U~#t4bmh{Mi7cpBB#p@K2W1qBL(ZtI%t*D&!gjAXqe<&5P*>!4qH@-hACfc1 z=!=ujsB2Puc7h$zD3o@{YLb^^A!I3JDZX`zZiH`cqdviOQ#$RC8l{MBkU4|AM?3Ze zZ-kyFdeBK^DT7j^P?Ey-#Bb35W(GiX0A=~c0N*GOm3n2};7|s%ukZp;q_^dtu(|=l zpoTq?R_!;jciG>`w|m@fA+JjB0PtCfELlYOWUkgkaLQD*5H>os=wBM*O&ZdF)C4(I z$T?Nnn^fqVW^nQ4|IF~%QLj)$4y(g@s^KW+M{`6|sdL{?zx>E3O?sfnc$R_90?NH{ z#Fx$?Wyv)3i68(9OtT61fKCe2&_&t*H)cDuW2^d0akz8xms`ZdDR=9QLb6z zFFUQ3J=O=FSw0}xTfD6NJmY-e^AGD9+c0x(@LujX6MPVQ34V(wGJ#!*JR^T#eF-Nr zi(Dydl@A;ivX)+9eSm&R2^>mjs9E7Y)AtI^vDmD;T%q;Kdg~3c5UyiC174n4d!@gH zz4gD3{jM_}YuSV1p9(U^S-w0&U4&XKNN1w-t;O`}v-jbv2qU`UTSI*L>rP+L!=gg- z1qMz$yr4f`>>G;=E>cg*r7bz|H^k`{lHNhX6&P)3T5;wC;HPVkPtruVpBp!?`1^0F z2HG=XE=?Mo2zYLIZp1GRLek%VTh&85!03-!)k!+A>i4JDTb>1ZQTsUmVg~i<;NU7aWD9O=dr(qP zQFaJ!U>R2kGYXQk(@%pgb=ZMU?QJ{h+iBz`d*w6c!wCe!raM(F>p>&M6=Uk9O5cUd z4{{o;Ha#D++ioi^+aA0BB4RV?by^(PzhuFwx}vwjU_4ero}_cuEV z2nObE!3qZC`ms5P;FV@PUZwemTF-kJb9Tuo5&&7x@5#c-%FF{$m6J65{9ybiaeErA zEm0kuI*gXqmjdIe9SN4J=gid-f0%UE*zreS%FRQ?U;0jZA>fmv&>h{}AK`gC`(2?! zK?A4Ii^57EfB8MgT=|W!Hp8b}6a|onZJlCsz|PZ68=h0qc%uHYuaDD%8`4h=i5k7FC^WdRt@k2ANnTjVpC zZlDNYQw{Y__Lpwl93Xvv^l0zT8ZFPK8g=vGuTa=L(d$ z6;hYqd)~$y^VMNw3^#GWL0bFT8#0xU1^@{S1O??`GyZn=6+#*RjUtX-H8(x()%8>w z+U@KtcKm*hZ7)%~s(4`2Z_>%ZdSLb~OYP^a##nD`3T1#qw@^8n=oAfVLh(eT`^f~e zIp4snYEB(~&@Xs5XzAS;1vtA7ZKfuJfm>dn%AI*s>z%g8d0IESuwgDcSr++U#vUMq zvYTLAxt-2N777eRUnN5|nVYwPI-$AteYg247yF4VwQ<@|7}OAK3C$|{{*pz}QZz3MV+`A5M&IqejQ#iW>#Q&pV-6jj7fSt)}#4tV{mlH)e<}4P{*)4~N26oPiQ$ zlq~7|Yi1dwZUx6C{0`D6Atu67p|VCG$;_t4%$NX?pSFo*pBpBVZL%_WlHYm;aCvO$TFj<$8em}U%P z|A0zNJ{s1u7HRxJspw+G=y46QuI|u|gYmWe<`-lwCL&rw`>xSLoJ##=_9D z@9pD4Ru$c*VH2-!vP8~Mvc4XWkbVtb0+)OZT*zfNTIAgkZsy&eKZX ziSt1_d?7ZRXLNAKEUwW#`2o!!DPQZmk$ub^dlwfueTxpY2M(d#mj;t?fnt2o>Pb)k z2RMWT4Rq`!+xvikSbIj-wigzkBvNd9P4g)5FbAl-u`RwTR&PyU9XR(8KGcw& zw+SY}{7Y$uG(=GM^UcEp#bZ4tW z6b*Q&*mWP}UWV3?t-f182FhC|@y@9{>Xu;HrQ|WJ>T?SmGWRSn%yT(bO<8#7&c~HZ zFghN&%(xduLA5=y8-{oEinr>pC_irohDOW}>Qb8AQREN!@rB;y>V==4aU|5pyH3^2 zZ)$ntpU4){m`*?r^gJ}h<+HY-pl7;u)ad2GG8y&ci?aBn(7P|iD8=y}_{8dK9@OV> zhDjGuvrETD)pK`1%63FP@~WSl*Q8MPmP*YFa@n0ah{+wZ4v$99Wa|)2mCs_1S%~g= zKjq~;zdxGzhYQJ#UY_!F=(TJfig*c;MNQkym*V5p{1 zlM8|OJ-eBg06KAVZV`03azxua{RL2XHEnXt)_D*XS@-||Vhz%@7pL#T#_GE$1sGvf zTf~N{F2{P*^?X0fai_Ngy0a-sN#4 z)aFefA93CLXKNX)+;EiH{)l3f?bwkrdAsZJ>+XvJWN~DL) z{7_c^Dyr&uKz2Y{fu7xh?n{vT4>UKVG`mX4d7ROBLr2ji67qk20>BL_nY{cTL=lRn z6~XY@0h9irMgsm`x#&Mo{WOMh61E6G+)G|bn3208Q*B+`OBN{9OK!KQ(|&&?r^|s{ z)%4?b&^R`9sgbi5@0PO`%aW@TOjCkviI{J{ogDJ=0DnUtKnI}_psk|S04z8?!LGlM zDe%+LPB1)XaF4F;XzjYA9r}j;0B28Op$E1Oit4+){(CvSGe~e9vx{&|DH-4 z(O7*!9`)LISAFzN>+G3!!|?m!n4$86luRjx$TOxHzZvT%TC9w;4?6J%^zvVG?(dpK94h21I*$?Pjh%USNPDa5-*dx?ySciAQ!?!4q}yYg zEO3f%S)$Gc(^f-0^s8Q=uzS!*_3hXFlLWL+e~YWBe&0YDQ*1gWX^oAyfNRCGCL$~e zbJ@s7sq{o0vV*i+|0V;`bZpxR^uqSq8<|y5gP~4(E;9I$oEy+|!6c(*w+`Le3^V(; z9~1sh#Q-LHHi9Qlejb4g9(l}0;P6}i3$?`uI&|#G^|!KIQr@i^YVj{Q{?4n^wQhAC z%{n8eyYIDva$(sQ9?o~nuEG(H=pRgveBS(zG0pe*6GjQUMulFgr``a5punmNT~uv#>xH?03CK&v!r1sIIk!wHW?& z!>yI^eZ(B{^MjW4aZ0eZGfVMMj+82Ft@^d@`Nc*ks7ME}a-nX=ik7SJx~d6n zqV27@y<7Eu7zetD7*Bt__(Pz_G4X@Z4nz0%_qS@NXxy+?+Vv3qfcH;+*n z9D#~>b4ATvv)yIR5{WnMh5hwArDtPse8}{=Wp}8{UykE?7km}%ap}Jvmp*dHt zU54p(KYtPLXD(H9Dx=MJp6fYIJ-d)&!?>VX;9n+`K>#U&F*H1UPEu^+HOSS2G%~dg z<$mQfqIzHX!U>Gbd}~@c@%{F@QvUk(cD%9uECD^{P+iI1aKqrNfQdwx_g=c(%rQ1v z^Ig+Xdw=Q4{?Fo`d}fC|xm7#&O;sb8e-YRmgt|U-$e8UujRPU}<>lC)L5ikb{9HJw zUy$n2bTvTW7cSc`&ysyg@y&dijzM~-p%OP`V#RL7EG%7VwtlISjM>%oCTeTQ(R5s* zWby-$SmDZzWE`Xcp&71nKoRa7EYUl4MEz~`6j1>c>GxotR*~#t!8_4~7v$Y~$7u-E zUDH68N>VO?q!m-RJ5r=msI8zI9UrMD4g*BgUUlGh#%R~}q)s=+MmQo*D6=cUL}ZW- z5H2ocu3wf0RTu$Z2g*;N7Ma2e7d-O%g+5_h)CbOp$~%(Tq^8b=xmg=-NQH2N#3_QI zHLnUI(Z;*qZdttes{9HH38-d5iyV#`*%Qh^6Io_TpFk^uuj_o(UsVgXh*5S$RZ1LT z4FF0YHHsZEb%zSxhZMNLPK1}#;%!iJsnHRmPeoiJ02Ar3A@O)h;a##kC<2cgCeSYM z-wB;UVSES<$9v+>sG4OvX*IBd1YYTgtBlF`>NC!8+=sp}K8EKZ^}xXpD*LC(2%lL~ ztiir)6FtGciXDDE6m`Z87wi#DiHa;P7zCoKQ|HJZB9MslXFEbCc=0&|1FA=zmLXqM zxTLpvvMK5)LJX9pQWo}b?DC6_!M9mWBd_4e&wNu`P+w_^Y_Ay3)HY{{0A$U1;&NjW zY|#Q@#MC3UN$(Osb9^rndoxBey(6D;+BN1^dg5|J7s!bSUz*jjg-0x4nD`aqD-iQH zCgQQe@K0ez*X&n`CXTNUWttwy#PP;x&+tFLzEzT+4m(+r)J_e3-C^?$C$!tZ^<%jc zI~ur>-$qsSR#*eUT>RxB{IK|S-t$O(08&k&L!=?8A0UX9@1xj#d{CBM@}iN#FIW-J69e2Nc5u2|P*i2W6l+?_Me&aMlJcAsP?1<{D1h+i_sY{r_56P5XBmjw{rH@K2A zF}Z9smIpE$GR^f2Tu%XZ2HgWGM;T{k-vc(td(QjF)Gs`@FL?w}h!oI>^IU%EdeO_P zpbkti;|$_Pgbh#pdihnoAJ3r4Cw-!{Va0)HbRE_PH8;tTK1puPLJpsZWtHs< zwq%N?HzZsj1Gn9t>BF1An82rtbeM{Ty@yIMN_-@<5$ucch2_M2q#&KJXk^9yPLD@| zE*j*Bae=m3VzeB(Ve@5O{xQj^HVk{Vz@rOnkHX29T6Oa>JaV+kf)40FYCXznfigyY zyM<|o1C#t$1ve;$t&lQsRJRwsSI~iD?Iv&Y2MB@(rc7L!g}j5{O?j?2;;<8$ZP8AZY#(y0^;+`p=3$qcpW&(rPheZP>?IYBsZ{Wy3bZD@xhWdb#TQ zG$@E9t2ftVGvao@aR%5w{cDT2vE$l>NN+-RJ|)m+>e5L{eyML#udz?yHDh;%qKzVu2Je>`&zYUR)^ZHtbWpjSJ8*dm84(r8CF%%+iH` z5$8eFdnc5xaRupacfFAPTTInj?5uv`Lno@^F2i&5_ialaF`DQRy!ifi&SfR|U%otx z8&UK=BtHhSXO5a0wxqLLqCJM^ya-fkOE`}{w{t3tZ1Jah=@4lX+#w2%syLi-x1vj# zqvqtNeqgKl;P?S6f~LiNNcMB&7^dTkldO|!Fc{~dWK{q`@-&U`_lVx5nBjq~BjKz) zFy1v#t?3HGs+q3DjA+u&;v>@{gyMVds~->}Op(v4M&#h(d0>NLPORvonqc^6$}g0| zj=3L518QKq%wPu$VDb)FHr|W3=*tIEXy3zHKime_kxYOidGHBv$Ijd~=jBnn;8bKMlOBn;@ea&`iXF6x@Ri5#7a(f>q*c z7X@-7g$&^qoX&5YW~_&XZ2GfRH8{!4W{%yGz=Wlfrsr$1V9^F?8waf?W&>Xx@(;X( z;{uo)hHYoK7%w|cKUwM}kOifvo-*I5XFDy0q7r8qfk0B&n$kckUILhx>dd3WI3CT3 z|A7Hw9d>XNFh4&~DUO>-D`oFaDd#5e5z~6{&h)Ri-`vpP-`{8Znz^>o zx!(q*SWH2vbd=sF*r!~{lQ&l9RCDrwTAH#77Tx^Y?92VLJv#$C?X&gOMG%XX{wNI# zH73rhua39Mz7PjW`x(BpU$gsZJWISp&)B*85YG2)0xzE(9|T6E;%6LxbE!9kdLP6C zsECfI;M_|FiD&q`NO~%M=U;vcO1}lY>`?rMqH=GXBK`8Yo6K$ZTq~C0uUfC&*dC7I`1mdz)`82 z!D`O3SRm{sasO0MiO-c|I7WL9uH`!xlOz5w5k&DX=T&!1?QtJs+Ja-11WXupxf?er zQuG)sHm0bw;@{Bq3UDP&oDNJyhcne%zB`a{qUpx;cL%Jy_QfJhX=e9*4MwP0q8lUP zFFEi=n-$v>e%>YuKgc%e))XB0amldva|1jW&jko2J6MLadAz)DC*zaRwa;_Jb0lyy z>!EyQu=vAq#lh-O_ z>%Mb95s#e0Ae&qKAj_U|KwTxrmt8Eob840tKQ3R09mYErdaBgMMO(h{x*$-EK0il& zN&{rg{Hv_{cP+vJlJlyG-60OWN&3udmL&4b?R%n*m72BNDMYTic5Q8K4Kz+2CCgu^ zihz7Gw}J&NkxC+nFRwX*6kiGKtDpmrnyk`jsN})tbPy!szx-$d++=lS*946P*9Rt{ z386$s6<=Nd&f(7hjeRM{)N-cQ7pex1baDVm=)!x{?II2M?K&7(WvwC(Jme>pnPIE( z)Qz}|F!}Z=vbcpiTnsl+3T~HHqH*o~qHGeKnA=@P8O^CS(tJ+VNsI_Jx$B<{Z1Ihw zyKPY6TQR;}6{K{nbql=b@N8EPT1I;mU3Iq7dS%q=uYGxG+eIuJCYJByBWJ-NF@FTM z$76?8=N8lH4Ykh7#7mjgP;0PunAe-zAmJEI3_~U7i+Jm)*sFB7oU~<5a+MNt0Y#prvGWF+1xQ~sz9ev^4saD&R$#ZlZhnAcJ1sf1qnqUw5!*dr*e zvbTn~rTG@wFHt8d8E4!?plRpU{ZTd#^e60SBdh1 z);syEkNyr;cZ&!(@>&t?J(7b(wdNDJa`cM}k!y|P zqj~71jOxs=R@mc#;tv8s+P#SHNiWD=`mtVqWU3pV)}h#b%w#f$+}J_uJ3Jng#gH-F8&mhMHE*d`Z^50mVI8oN97K$ zufHRjlkaZ(=O$ZTv7h6pK*r*JseSR~>bf*xK3Ae)vzCQH?N-SL=!aCUpab8zgG`t? zrqk|BsnZZ#^X%oZKLc#5-Jl=~UR?Ui5XjNrQD?Qf7y|GdA@+(8c8dK#sfL;J$p=S_`QOH*p9!M+_Pq(~c-3oMIuFUT z{Hu2YBgVlG~masra7m{sL6D_Lz+h)(J)Ltnf~%nIM2$y(!pt+oV(Vl;cXh@Sb9 zo~!BX6}x0r?x=%0U9K1<*GAtNKcq}QCT<^-riJ&|o$INipWg4L?+Y@uWl_3ry*&!T z`Zw!*l0WJt==RVqe-kRE@H1Bl1&Dr&j&7-R9txlfqHEv@?4xahEtd+y*FxotEr9ePcy5#~x;q zvrgP{6AHzUcWA*@2WM1%f%fK~O^`1rH~jEwTz6`R5VR@6F!$cmq|~CG&5}sTq*-CW zqX;_%VcQ>A(BN?t5 z{eJj3Nt%D_FmqFtmo%yW%3m}V!u|zavtmo-UN-Gy4>BwBZ10smTu5)s_p*nFx>Td zZe_s1)wcC8&}r1J=dt=x4D&*W?Us?v0df6LK1PZ;S;4%DRWJ-2s*t^Vh#-^yCSUs{Q=4czYDYSyQPOebZg}uQzOgKUK8T#`!J{Svg8$nyBgoL&|;ljrUFH-i8ahl*qzTVAB>kHYM*Od&m~2OQ-Lqi3;wS;iF@h z);vFAfY1xcJ&xqvWEaCnI?`?gA}A!Pjenti)nJS)G>6#u4rCFGt}dd~P83JjIxWPo zpNEhPn+w?YVkIM@S&|dbhhug*cRk9WZtpRiAoa+O8uh5`|39|QF}Skk3-@m(6KkT0 zlZkD6V%xTJV(Y}5*fvjW+qP}ny!m+lb?>*XuIlQ&ySn%8T5CPe59Y=f7w(Ug<{(cV z8g+P_XmN8~>*@DhQ%x~zQVv4E@EvLwJ)T4}h zN?QYom{vvM>IMrs=Hj#m!=~e@EfzXLnO4RTwR~?p9_@!m)X5DVSBN0oYe=V={OAhi z#!uLn&1&<>vxrqrj#%2Dpa@+c9!3sH34t<-G(H2o5k4Vq*#g7Hr5&`$T)U28CbyVS zs(AI@0}%F^bQ4qHmmW-q_C~Fh>aomf5Snqv8`%j?8LBHgePLG8-m%VNPJvinff0kH z6}VVJUaE$1`^jYa)w26w{U%36!pz`V)7rZI$DXy?Ly3Rgzpsy} zB$vF<0N^iS9S8KtR~g>E{3ZFNAjk3j4xk=g?dDdt(mzp9o^-NhO+(kumAKS8c_3tk z)R(FJQyz-n_$6+R@fIMVZsva^9*lwG6IcD-e?8LVsy*`AEjn56Uoo0!u-Po0dsWco zfRoL9PE5umSXG@d&V7-jOHD6!%ry%?TM-mZJE$*ZTirLV?X|#9JdYwb*;h((&nKqg z@*W4zJm6=-X%TX{8-l}qHf$z$6}CgKpLS_?hqnFY5<1};qzsdn*}FAQXfMcn$zSy# zD)iC~h8au;O;?K}<{IEcB5{d_hKBlwfM&BaJ@lhkhR7#!i(%2`TgaQ!W5zi_U&f;v z_2_i=AY!>fE@DL{=`h!N6YO}y+JjWd;B*+*TFDGzq`oV7(t$-)@)RH&LQpnXdO?3; zz$G_bhbWop3hj};d_aU+G6Q=nP5g^b6dz%0Znlt_7g0B*+;tuF4p=<}V|GXz5WI?f z6Q5vZ`9?Vi(GMNjwP_lPKPW2bcl-)TG-ftVCJxuBhs)sHRfi6<5wlG5$+<;s96YgW zObGir$~mjaCsHoIApd)P@Y`&NJil0ukLGnKm)uE=-=Me7J0{!UAJYMh{-?&|wV|~E z|7Tg42$aPztNXmQ(L|=fLv}3|;N(5PD4FsB7LiL1gy1|KXO#Q9G9asK z{`)pNY{r>tM;hL=#;6=i`uQNDTta=I8NhY_OU9%0HtTh?@x|zEll?X|DOzF>!}aJ1 zUsv62EvJ%uU?a?;D!B7&ZSu`hG|{+a1vG&t)0k^(z1eP6KGDy*kNi&oc(^Csz#u|7 z8!CBO9>9UMf@~cm0f-tNY{Tbb97vqWx*Rr&@NAI zC)+A@R8aXRT8wCDI7twviL$^y6u-z@7V4i^`*#3qvfe2-Uu!XjC0En_$d6|;m#SG4E6p;+$e%hSX)tGVH=%9j^DQVnD~f2XT= zw=(Lxjb@O(nkKt%@sxT1k;`3FEYD?ATaWlKUGBvj-(T~QZ%uRoCSUXfWpa!7 z+}rH4p7JSNw_)Lc45eVg%46&8Jh7nSsVc=n3N}6@VG$a1(7;~a@o(w@s+;oRGLcVX zf&UQD`H24$_&c>R9GPA9D9~JphV3$hgJJrNwKjNRZl=M|76D~|tc_<7m#0DTqmatNoc~lV(dqWUUbtP-7^6P| zH5rE2-3#oG9ko-*5eaMV4oqaB{9S8z)jCC6GUX%-rA}LTMWUs83@ej+=RGd>z+^AylUBiGyTfA-f9NwRf}ZW+CDK#< zlV4B!FMvVl$GGx)-14ur?O&CsBOEu?;sDjI8DsySa8KN()5~82#j6_t=Ff)OF3&3&KvgRHaes}#W8 zx;5Ko6xqCX`C+)0_X@MvoFumb${lqfj*uF{abC7}e|Dk7@>an$-mYXfGngg1%D*;0 z_jr4CJCPmBcuvg3; zG1nw&t+@B_=$ownqy#i1NWo8K)Mvpfj`xyl0yNXsQe~wYO^~&e)7a=_0b zig=x`03&sck+{AsXZv|FQxDjoLWv1fWjyxV_*nJEJd3}gBBCC4V~Q$=mqD!XbYH-e zd`iB8Wo2y&?A>Xm+dOh?DY{X2q_@<>b=&cGu=Q(+ei3!g^U3q$$Em!zV8WX@C5bGE zSXy?@l>Y&vqr!v2MnyWC>oFG) zdyo+Hh(t@kE(}14|E=;8I+VPZ&u6<{_?qER`nBs&6*^d2_V((ibWmg7ljq_Gi~34q z7&%y&Qwdh)QOWDU78!j5dr< z242nMZAG-bb$MRZWs|w+Hj~~XP_8Oo0yOCFrD)GwK4c(cujZHbR_-w7KiNo1wAb`2 z`JOmTvHjBz33?W4Le?WG4*7x4H4y>}#rcJPvloY)o26^>6Qd)$(7 z4wDQ)LOGuo8T|q4XaEED`TvZYW>fXu3~amNqm$D`R1l{uB>{;ez{H8>5dzJ^LEXL3 zR_TS#@3>LqH-zz?zDoDic@{KtG^%iCGo+n*U&bv|6i&+g4IiS}-|HYb%Qc48kN z`uA3=%@0nkY=^C$JrDBS`T6AxCE9VhP?*godA)1boXC2>=dO_YsB;MfLq;&dKp0cl zF-znf_uOX#`K8WBa7oRxOJtOs1mevIk7UvVL`%V7T;UL*g>RX$4 zX2=Gg%|wJ?4kudc^-J0%K6VPge+@?bOx6aRmir=5vzGz zvXB$Ab7qAM0kazJ0kL81)~E_}c5{{=$A#7t99+OG6-!f;6&M#v)Y$?)yG$qI%Dlg& zA%AJ;Y)C?tvK^owoC@-i|Mu;%JB94paQT1L;8eDHh#uBhKF}XBs>HFAegpA+tgjt&O(6!Ck3F{|Z0RdoMA079SPC;F!N zFX0Cu?U6WRYB={WEA1DWD|^Ra<$!vkVD>fTVw5uk!G4_2sM|`R1X}!g$3!(7qQ#?uPNs0_tCIk~LBczYlEDbcV-vPKlAJeQ*8b^p;K zO&Snfvkq9+&#?iA!3h;$T)Bg<{B$R&LSglRz_1RHzPfh1RpB`y;OFsCZ2xt2&X5ai zW*rr)VttW@K*|G;Z9^^d$rBQYw-o60POW(Gv-sod8KYk-OapL$c;Yz8d^S?_%=l#$ z{ZwY)7l=K+AwtvgG zl=#f>9A%C%mzO0iY}Z)`vLy*0Z{LM>WV$#6KGVHXVNGkzV@(uHn4t)# za>)_p=OWSVGczw8Bwo+J(MUw--R7#AP;OFidLwmXJ6|2uWjepjxZuCjDL%AUzI)GO z>*Krh(WSX^vo|%sa_!m3Pz!Ji&)<<=kk_?$Y1Eg=v87_2ZAZ3yV$M))gf?b+ncxn0e;sw#5h-0o@T-#iC*K4wI zWK)05WGPMgLu#106cRVx>{NfBb8?@@h=q>zk__I7f;n9U304&X;tVJdqEZsnHsj7f zbK5@_c!WZ4jN{&Wd=YK4kod>bD6_J5mtXHw`JNZG`)>k4(@i~|yLuo??Uam-_Z6zU zZU(*N>;OA|x%aWyT*)Wu;donvlQnJ_LdM&+)3KN#|J|v?tI}mo4~YFr3piJBo~%b| z5r~}n%x>R-^{*BOc>$QNBB`a-qFhPcBvNleTQ&$$(MZ+8m8wg;k5w5q=BP`5&!A1P z)Yl>lid0z;nQ9PaJTZyKN*2V(wqPnkuB0?&ZdP^JxUtNTFbTpi<9P8BHk#jvu##eF z71CjpjUhWGTP9j1Qc3Xaz{^LicOH&x@)#*B>lF=53vWX5qy)~Rc{Dug?poKFJf-j& z-n`rAV^nmNW)v7D7!gf|loYmD-XXa1yp2oA*~o9vXBeK8P}jtWXW9G*w<b6E|M(izGz9J!|5YFoB1-%rDb!r1He(vZP@(h%anyI4RtReu%Mk| zz<7drr~}3Ik1Q}$se!OXywI&A5>z~f4qpK%ERsZJ<+SF(UOSK;CdRWqy&EKv+ix+F zG!2AY6)hoFC=AESG(q^{Ci;#0XqO)O^@D$I4Oe@;)B~%Xgqto;cx9w7o}AQH+;qgW zN|Z6}PJUZK52N`UY#-|r>Zc)|q^NbQkObQv1YUW7ry-CviONzTfE5SvhgFFfb-8f_ zm!Yhc7AOx@Wsg1)th!sZ`}^}YB~dL4IxE}!?HMtz_eIa&qhlVl+94r8nd(+dw)x#K zC?$V)cp&5p{^tgHoFfWzObe}Mj|2&+JtS~l#wa9BQWjAR{3TXAwm-5$;pHIkI zF@k8F8<@9N?X)wQ%Z~9Ig^A&9hTOIC^M^CxFAwT^+sWF^{l=BMR@dyZQy=sHK*~=; z)^Q-^NomalVF09&%3ILj>EpK#89ecR3}SsiPRwO}o4gHOH0=}81a7!chknN|qYJ}x z{j0c{T!i4u$GCs^fJto4U1w@L{#l%VuQUOS8$jdeXe%og{p%C)gR?Fr9iVfnjH-&T zvxiWisj*1X)=~8IqdPL|^dMYSJ{4VI<5g>!eh5>8 z3Vh#V8iFJK-)q#;{JEU(~P70x@z~Ea*@OYzJqv+z$jzQ z&23U#P}e;_ZCD5NSPuVjEAuVU-czN)=RfS!J;~gQ>v(+Z)WTnDbvz)6q%8yGw}|Ib4wO%&v&c-Lqlp)OTV_fTATPFd;>!evF& zJm5IX;pYwoH=H}SFS9V*NaJu|i|Xgxiy+z^sFS@nU@V#xyHX|?+G}Q}m~&$d22P`i z>TTc2Fr*Id*rXJ2pZuj;xwLGP3{9P9^gszj(YmKR;HBb+T8 zjr1mE+s&4AA?+SEsd$r7^^HSL-xlYn>cr;JF3eg24e?dq< z#=;zzqCcz@|A*duC6!0QjF)Jy2b5=>OivriNIP!-%z(;by$-D8yKfXG&ZT@eX;1uv zPck|E)IZ{a{M*u|HLH--dvXdNLySY*+Y)4adlObjRPj5&FyBr7o%6QDB}+X3iwIG) zyFyu+TQGbOP>ys~Mdh|owY9?(?A{la6_!9OUt|Np{wif3$5Xd8wMLe|> z@Hl_(bbpP-Bj|GY2Vi3Ad>A}#Rv>dL+9zvKOqk-%aOYM8!&JvCRkNKqUd2=>J&>59 z7WlManM>iBdM;V($UHy7W1|w6YF(o_hl+waH|tCxTSq!!suJv6ULPkxk>Rl_#n^^2 z8;8PZt4LHTO%j&U)E5nf5A0N0{80c(4`~clDnyOq#sd{m4}=N|TYBiWI!rXUube>5 zc1dE4pIqLbI)Tmdo^YP*I3-<>2~>tWwNiZbrQ2Hz z>Xf59Rp#jg9D61;zP|Jb1;gX}I7T|an2sMX4dvrZp%%1n?uUSn7h5SH z*=$n=`xorU;0RSK;2*OYem$FpvVzY6yM?`_f#ZJ9)YLLT!9A0M+$$w0wENWGe-AK{ zy|r)5f$TDyTt$v2@82bvg%w*f-tX^i%@v6K&3g(NrO5g7VhNkY!%t~jhCUHSwjbGx zSr8nRpw_p|&JQ3-g=!o1N?5jPBgxq7il#=AV4kxzbq$^da4;z|WpP=qO>R}~;!^9% z(@KMqC73CYBmphlsPDfUCoWWQJZO7KYgi#oMZUt!+cEe8tWzcfajt?Cw!mqLMc$+J zHUf>8zY(l&o9<6po}W+aQ*CF7*{-8IE@o|Ne6wE74|ezB@8w>T&XbO8b|Y`~?^Tm# z9db}UhwrIpz!&{H;w;;-ul?7wqcbqG702u|Z+tO0kzD>@vT%ya;pVoz=d@jHcbSs- ziWJq`5zcID73S6@^Q@4TBxE%b>7&`1MPtl)!}ocOr{Lgq@9obez8fh@jhDqKe#MuE zkGNO)T)RW*-0PT(=bZi4uG>hx_uAWrC!MzIQaFrBAaJ)AV*bfbQkE0$m94M+cCWMt zP|?&hx>I1p!?BsBT{l<5-Q4DUl(toVv%6ZrwdJ+)klj(gP<1q+c#zF}H zT$zkBini*BKV&&eZpJuGb6(MK;|cAw39iU9mOr;Qlhg8JHvf(x2WJN3w3E=41UR)3 zcH-5JEseELY#P|kfZVt*Vfb;AzH8QCfPC-3%xV-H(~Y=*`{aYUS$Fm3h9+sWr25K%{A>;5hKAAbob|ZD4exD1n-Ko(d+A&_---axGlEI@c99ZoNX-!f^-g z$}M>gwYs(xy?gpI%P3_wk*$Y4@NO9S%}mbpn=c)EG>siu-?$70@cIc8%^c`vi$7@j zDa9T%#^a266PSDIZ4IqW-t%U;wNnG#G(8v|d!C10`8J-+yQu9?R-5cy7AP-aRx@;> zr_|^wwWhMyxQ{s-AbkgN>RA~RIWXSMcT4+`P%0;d|CCVRNsn(WLr?D04MLKUGAy*Q5nYud&QoB>Vu zu40!SCm8%5GT5t5+wxbdgblQ_wNFWX1Z`hq1RnZ#v`v)}E*r~@EZT$j3a~axLqu$I)G|=lH9M0Wtlg<50OpLu| z`DHnuamc=z7t67qPGS^jRQ-1d0?(??mcILybNdPLB^a|@I7%QI@}IKp`V1Z%fo1wX z9^4nNetRAVuG^#7E8$Af44PS71>!zr(%DV>Q!nT3t+!*$`;+wJ7^VHy_-2iFsx4|8 zpHjTJ?uh#esK4HbNJP;rVW{GwuP+`6QM zGs-)w620%f2g3m*K&-?WiN2)`y0lq$iJEuK!Fwa?G^Fu4L@f2*@Eci^@>YE73pw0; zNe$V*OMFKEC`!F`oQ-EFgy8*PFms1GJ~8`BwRC)RfhXN?v)>sAz!)mD;%|p`O_K)U zp^ijT$Bpegxp{%{mt*c%=l8AcNL7Pl3Z|%AoN!tH;4%rV;qU)`t-$N}yganl4p!^%)O7o8I#Nz5@%($h#ZPrUwHbo1$ zC3VLn6E9Yh@lzlxjfufk^xUQlO?H7#k-0g+i0&1)ug{d7n_=d+g#+%`hw1uAlC$lA zS$!VjAq@Zr>^$oll;W~V#wB^TGD2GfC%!10RlEOGeeB!1h(JN^<5(OL{6~!^MlDgS zgmmB9RXTjMo?K{FSiGSYARFB#6xQaUV`QCvvPgi>W=q#1Ku2l&0lu$q9J^2-W zhTh~FFne)%N16z;g=ms}WfgvexK-}ZpR91(sWc00^CnQicL0t&)!&w1spw7THXDdw zs3;dsvFAy@7NOau&t9fqU)<5Y;wxmycOH0Z+_d(rWAxeIPax4Z4qW??F8nr^kPM%y zU`VyWKYZZmj!^4tw*TWkK}eWl8D1&J)oNlZoYWzkyhUGD^-B6viLvC-mDwziv3Tqx zkZ~Qj2LaWa$NQCH)eqN{u$4dclK@c{hRYw3CQ0mF9k+9o-TgT^^u9Gjb{Z`D@nlsY zI(Jn8$&0f3MEIfOzmPJ}6J{sfMj-jPYywI9Kk;pjdyV2gtRC_!oh2(u40)y#?u7$nB-nMe z-Rwnkr4NT<$>OS)75zVBKpLhMbcHIaxQJe^vmUsEDN?gXN(MkBJBst@~8#oMYaUZ$rR_k9{L=3TF9G&y>5Bg5RC%^Yv%3u=k+z-AB#kx>Jy zgB;wF>lEQ@a%lgVq5`CSr#p)Op{m~h!VAW&vHsHTt3z`c4!1m!<$wUU+}FBM3~_Gq z1VsQ>!FSb;2_Z5l-E3vPcgIqi!nc zmh6jH&fl)m4SN?v4smYmca0C$_Fooib^1gQ+>giV#l;fe4r{e~xo$oUD-X?XpGHng zSdMPdydwx)r*`6ZJg|^u{rk7)v(s>JW4HnT?`IT~CR&C$=v0sPMgJXHLAd;F>AO7f z-OtgOs?YvP%0{ezEn*GTgO5Og)Ia;(&*MVgqq`F?n~EDRmx=~NevGa7RPQ#Yj@N&; zk>PL=?S^e*bRp;gs~r&m%a_3?z#MEc2&ni=s!lnb{j(fTvbcjoX* z)-G_rg-k!;s0+p>;8wg{ryEvjZ@o*QKROx?^Lh{bXA|nD02uKn;Ad42W~kPWV9ZeZ zUtZuN%*6T$A#WZ)yqzs_{eB>O&lw}+E)pE3;h#^8pHI2oyK>N&=cr#aJ>bGeYu_{K zi7e0Q1LXofco96@vF~A7wxO`E!4Z65ls}lpk~CsZtg|d=5L^?zvH9v~q^?<*HNf~9 zyA@Xu-KfC+sUeIa^vdUwKwUtAtx6oMe#Otq%P=M41*QRUKca|+YI3aE*Ezc;tZ_es zSA2aN}jSve~zPQdyCJyCV1xyMxgQFAdw_+|t zqgXh^qMUZMD6y=C0NfXn&L)!_nnD1Lcs6-B zRFVKfCrT6`Ab~KDI|D;+SkxwJo5fhyp5OW~0pLF1OI6_qg(ZUj_XvZ2@ zq&`%k(bUVMPsFOL*#sgiw}O>{@1>tp+5r6)v5o>3cz&dmJmP|i;1&YR4sg!6K4$%g za20?Q@rBIPhDv7SIqjAj|1O+l`rN|-iH6%~D~ox}bt5=%tX28v?OjHCr&SMRQoU<}aeWFLK zA%z@gJ=NNFSvyxvuT_)c;rQPZgPzhf6GotvO#o=r!w*ukOPJU1DJK#^8PZa@h_LbO zAUj{3KCCml_*tX;<>f2wsm1oUFx$LH6zGUb_FJw9L$xM%p|U9RUbMpn-hM>s0aERI zt{>jj5CFtnfVXR43KVVEfwKs@K}yzqplM&_-0H|X{Hk0=vI&Sa!g!ZaI-!A^eFBzx z7Zeh{?mq09H)KeScc`I#Ry>6)Jnrme!LU&%1RBG%mC3QbsTo;DStf&ZY44?09w^wf zF*Q^i@$20G8drSCm~adtysaa>9r~d#WA%ao@D#S|lXg(tzi3$<9&%r`HB7Zkpj}|f zrSoXgJ>w@GRcRc?yCZtko6=ptj|Tpp!zr0(9<=nqLe|3^b4&Tzt&vH*aGH;du&I`hkF%O_;ZQbOCsaFDfYsi5&KE! zs^fw?ew1x%3W5XRd7Vi{msa~IVAlDuQc3hfI_<+)SeIAgu9|d_Bi_^MO6}x^uQcLi za8#j1(zb!1rQx)0k7Y)C0~ig$pR25Uc)ub6Y>a|9%QLjf6T~r?O>qWCsUUDo8ih{& z>r-&Rk*a0H#8PRt2`&axcO=6356vW)wIZ$$ju7jnHaDr(^EPf(Cm z=q`c$jL@@%@_{h>+*vzROnKKa!{IkAdzvZL(7c_WLs&~Y>g3DxU6n5M6xNbNX?nBF z|01rLhaJFU_p9>39y}jbO^w6od1D`+=$+>p+aDx@^~0N0*l3C|9EC3%v)tg*hm&Ro z*LUx<3xjTC4Fcp1Zun1M1CV{tQ6{BP&uF!%1MeobDo)d+`r-|R@_3P zfyMmi!C-sZ46RY_bd?P~mZq!>c+$6b@+QrRWn;z?Y_JLFq+E4&mW`#_nix>(qDoyN z-&CG^#OKl~jh#R0erJc2aH$ttcwcFb1Kc17tdM6!>|#NGzT6C>sPgVJX+gq?$|yq>%J_aVCSu z7(+a|qo!a6Nw3sOsEp}OoADT@ zke^P&fHi>3bJzfJVUzz~fiw5UR3zjCbFj*|#n|u8wADB-fDL8zzdY$F6fc2HTEC||O$%ga zpSooz!0$is&Y>LPRDXG$J z%!=l@U4U214OiQA&TjxHmy5K`23xjcxL4D1{ctO1NihQ7?$7=9#3e?%sf#6U&9FQwlUVnboPl)jFXp}7ml2PV31OfIz zT_yL=yH!yM>ma6zoMlTb8X#MqS3( z-|{S$d(y0Z)zWCUZ3(R$$^%jIp~=QyPN+93u*0y;m;k_=U=CAM0W7J} z(17h_`05Rxbx&hsOOg(|C<ts;tI3-2No93B8OecB(Wr$A!%I`s^P2mo7?zQVs9!fnZbJ zCI8~Bf8r;<$N#{KXD_%0wq&E^JmV8#N!4C69EHD%1}T- z(v8N=Z=xTL9(<~Sh+K`903RZ)6smv7*iS6He7E5N#&P2Sl6tzLjc2#gX?jP!0cc{+ zTeNl&F{cbPc=1nmfeQX#r*h_RtkpNcE#8{*Pu*Z4m_s~?7C#VH?7OU!O`iPiN^XrB&-2-sra=) z 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 Date: Sun, 19 Feb 2017 10:25:55 -0800 Subject: [PATCH 02/12] add tiny cross-platform TCP socket library from https://github.com/DFHack/clsocket (todo: hook-up to Bullet cmake/premake build systems, and implement TCP alternative for UDP server) --- .../ThirdPartyLibs/clsocket/CMakeLists.txt | 102 ++ examples/ThirdPartyLibs/clsocket/README | 143 ++ examples/ThirdPartyLibs/clsocket/ReleaseNotes | 479 +++++++ .../clsocket/src/ActiveSocket.cpp | 310 +++++ .../clsocket/src/ActiveSocket.h | 91 ++ examples/ThirdPartyLibs/clsocket/src/Host.h | 257 ++++ .../clsocket/src/PassiveSocket.cpp | 331 +++++ .../clsocket/src/PassiveSocket.h | 119 ++ .../clsocket/src/SimpleSocket.cpp | 1187 +++++++++++++++++ .../clsocket/src/SimpleSocket.h | 583 ++++++++ .../ThirdPartyLibs/clsocket/src/StatTimer.h | 114 ++ test/clsocket/EchoServer.cpp | 44 + test/clsocket/QueryDayTime.cpp | 49 + test/clsocket/RecvAsync.cpp | 101 ++ 14 files changed, 3910 insertions(+) create mode 100644 examples/ThirdPartyLibs/clsocket/CMakeLists.txt create mode 100644 examples/ThirdPartyLibs/clsocket/README create mode 100644 examples/ThirdPartyLibs/clsocket/ReleaseNotes create mode 100644 examples/ThirdPartyLibs/clsocket/src/ActiveSocket.cpp create mode 100644 examples/ThirdPartyLibs/clsocket/src/ActiveSocket.h create mode 100644 examples/ThirdPartyLibs/clsocket/src/Host.h create mode 100644 examples/ThirdPartyLibs/clsocket/src/PassiveSocket.cpp create mode 100644 examples/ThirdPartyLibs/clsocket/src/PassiveSocket.h create mode 100644 examples/ThirdPartyLibs/clsocket/src/SimpleSocket.cpp create mode 100644 examples/ThirdPartyLibs/clsocket/src/SimpleSocket.h create mode 100644 examples/ThirdPartyLibs/clsocket/src/StatTimer.h create mode 100644 test/clsocket/EchoServer.cpp create mode 100644 test/clsocket/QueryDayTime.cpp create mode 100644 test/clsocket/RecvAsync.cpp diff --git a/examples/ThirdPartyLibs/clsocket/CMakeLists.txt b/examples/ThirdPartyLibs/clsocket/CMakeLists.txt new file mode 100644 index 000000000..5f85d0d8c --- /dev/null +++ b/examples/ThirdPartyLibs/clsocket/CMakeLists.txt @@ -0,0 +1,102 @@ +cmake_minimum_required(VERSION 2.8 FATAL_ERROR) +project(clsocket) + +# set up versioning. +set(BUILD_MAJOR "1") +set(BUILD_MINOR "4") +set(BUILD_VERSION "3") + +include_directories(src) + +SET(CLSOCKET_HEADERS +src/ActiveSocket.h +src/Host.h +src/PassiveSocket.h +src/SimpleSocket.h +src/StatTimer.h +) + +SET(CLSOCKET_SOURCES +src/SimpleSocket.cpp +src/ActiveSocket.cpp +src/PassiveSocket.cpp +) + +# mark headers as headers... +SET_SOURCE_FILES_PROPERTIES( ${CLSOCKET_HEADERS} PROPERTIES HEADER_FILE_ONLY TRUE ) +# append to sources so that dependency checks work on headers +LIST(APPEND CLSOCKET_SOURCES ${CLSOCKET_HEADERS}) + +# OS and compiler checks. +if(UNIX) + # linux / normal unix + add_definitions(-D_LINUX) + if(CYGWIN) + # Special Cygwin stuff here + elseif(APPLE) + # Special Apple stuff here + remove_definitions(-D_LINUX) + add_definitions(-D_DARWIN) + endif() +elseif(WIN32) + add_definitions(-DWIN32) + SET(PROJECT_LIBS Ws2_32.lib) + if(MINGW) + # Special MINGW stuff here + elseif(MSVC) + # Special MSVC stuff here + else() + # No idea what it is, but there's a good chance it's too weird. + MESSAGE( FATAL_ERROR "Using unknown WIN32 compiler... NOT. Please add to build system." ) + endif() +endif() + +OPTION(CLSOCKET_SHARED "Build clsocket lib as shared." ON) +OPTION(CLSOCKET_DEP_ONLY "Build for use inside other CMake projects as dependency." OFF) + +# make the lib +if(CLSOCKET_SHARED) + if(CLSOCKET_DEP_ONLY) + ADD_LIBRARY(clsocket SHARED EXCLUDE_FROM_ALL ${CLSOCKET_SOURCES}) + else() + ADD_LIBRARY(clsocket SHARED ${CLSOCKET_SOURCES}) + endif() +else() + if(CLSOCKET_DEP_ONLY) + ADD_LIBRARY(clsocket STATIC EXCLUDE_FROM_ALL ${CLSOCKET_SOURCES}) + else() + ADD_LIBRARY(clsocket STATIC ${CLSOCKET_SOURCES}) + endif() +endif() +TARGET_LINK_LIBRARIES(clsocket ${PROJECT_LIBS}) + +# install into configured prefix +if(NOT CLSOCKET_DEP_ONLY) + install(TARGETS clsocket ARCHIVE DESTINATION lib LIBRARY DESTINATION lib) + install(FILES ${CLSOCKET_HEADERS} DESTINATION include) +else() + +endif() + +OPTION(CLSOCKET_EXAMPLES "Build the examples" ON) + +ADD_EXECUTABLE(echoserver-example examples/EchoServer.cpp) +TARGET_LINK_LIBRARIES(echoserver-example clsocket) + +ADD_EXECUTABLE(querydaytime-example examples/QueryDayTime.cpp) +TARGET_LINK_LIBRARIES(querydaytime-example clsocket) + + +if(UNIX) + + if(CLSOCKET_EXAMPLES) + ADD_EXECUTABLE(clsocket-example examples/RecvAsync.cpp) + TARGET_LINK_LIBRARIES(clsocket-example clsocket pthread) + if(NOT CLSOCKET_DEP_ONLY) + install(TARGETS clsocket-example DESTINATION bin) + endif() + + + endif() +endif() + diff --git a/examples/ThirdPartyLibs/clsocket/README b/examples/ThirdPartyLibs/clsocket/README new file mode 100644 index 000000000..8f06bd06c --- /dev/null +++ b/examples/ThirdPartyLibs/clsocket/README @@ -0,0 +1,143 @@ +Fork from https://github.com/DFHack/clsocket to be used in Bullet Physics SDK +Modifications: custom build system (CMake, premake etc), use preprocessor define _WIN32 instead of WIN32, __LINUX__, __APPLE__ + +------------------------------------------------------------------------------------------ +* History +------------------------------------------------------------------------------------------ +Written by Mark Carrier to provide a mechanism for writing cross platform socket code. This library was originally written to only support blocking TCP sockets. Over the years it has been extended to support UDP and RAW sockets as well. This is the first official release of the library and the following functionality is supported: + + * Cross platform socket support. + o Windows 95, Windows 98, Windows XP + o Linux, Unix + o Macintosh OSX + * Support for sychronious, and asychronious sockets + * Supports TCP Streams + * Supports UDP Datagrams + * Supports Raw Sockets + * Thread Safe + * Signal Safe + + +------------------------------------------------------------------------------------------ +* SimpleSocket Class Overview +------------------------------------------------------------------------------------------ +Network communications via sockets can be abstracted into two categories of functionality; the active socket and the passive socket. The active socket object initiates a connection with a known host, whereas the passive socket object waits (or listens) for inbound requests for communication. The functionality of both objects is identical as far as sending and receiving data. This library makes distinction between the two objects because the operations for constructing and destructing the two are different. + +This library is different from other socket libraries which define TCP sockets, UDP sockets, HTTP sockets, etc. The reason is the operations required for TCP, UDP, and RAW network communication is identical from a logical stand point. Thus a program could initially be written employing TCP streams, and then at some future point it could be discovered that UDP datagrams would satisify the solution. Changing between the two transport protocols would only require changing how the object is instantiated. The remaining code would in theory require minimal to no changes. + +This library avoids abstractions like HTTP socket, or SMTP socket, soley because this type of object mixes the application and the transport layer. These types of abstractions can be created using this library as a base class. + +The simple socket library is comprised of two class which can be used to represent all socket communications. + + * Active Socket Class + * Passive Socket Class + + +------------------------------------------------------------------------------------------ +* SimpleSocket Class Examples +------------------------------------------------------------------------------------------ +When operating on a socket object most methods will return true or false +Simple Active Socket +As mentioned previously the active socket (CActiveSocket) is used to initiate a connections with a server on some known port. So you want to connect to an existing server... + +How do you do it? + +There are many ways using the existing Berkley Socket API, but the goal of this class is to remove the many calls and man page lookups and replace them with clear, concise set of methods which allow a developer to focus on the logic of network programming. + +The following code will connect to a DAYTIME server on port 13, query for the current time, and close the socket. + +#include +#include "ActiveSocket.h" // Include header for active socket object definition + +int main(int argc, char **argv) +{ + CActiveSocket socket; // Instantiate active socket object (defaults to TCP). + char time[50]; + + memset(&time, 0, 50); + + //-------------------------------------------------------------------------- + // Initialize our socket object + //-------------------------------------------------------------------------- + socket.Initialize(); + + //-------------------------------------------------------------------------- + // Create a connection to the time server so that data can be sent + // and received. + //-------------------------------------------------------------------------- + if (socket.Open("time-C.timefreq.bldrdoc.gov", 13)) + { + //---------------------------------------------------------------------- + // Send a requtest the server requesting the current time. + //---------------------------------------------------------------------- + if (socket.Send((const uint8 *)"\n", 1)) + { + //---------------------------------------------------------------------- + // Receive response from the server. + //---------------------------------------------------------------------- + socket.Receive(49); + memcpy(&time, socket.GetData(), 49); + printf("%s\n", time); + + //---------------------------------------------------------------------- + // Close the connection. + //---------------------------------------------------------------------- + socket.Close(); + } + } + + + return 1; +} + +You can see that the amount of code required to an object for network communciation is very small and simple. +Simple Passive Socket +Now you want to build a server. + +How do you do it? + +For a practical test lets build an echo server. The server will listen on port 6789 an repsond back with what ever has been sent to the server. + +#include "PassiveSocket.h" // Include header for active socket object definition + +#define MAX_PACKET 4096 + +int main(int argc, char **argv) +{ + CPassiveSocket socket; + CActiveSocket *pClient = NULL; + + //-------------------------------------------------------------------------- + // Initialize our socket object + //-------------------------------------------------------------------------- + socket.Initialize(); + + socket.Listen("127.0.0.1", 6789); + + while (true) + { + if ((pClient = socket.Accept()) != NULL) + { + //---------------------------------------------------------------------- + // Receive request from the client. + //---------------------------------------------------------------------- + if (pClient->Receive(MAX_PACKET)) + { + //------------------------------------------------------------------ + // Send response to client and close connection to the client. + //------------------------------------------------------------------ + pClient->Send( pClient->GetData(), pClient->GetBytesReceived() ); + pClient->Close(); + } + + delete pClient; + } + } + + //----------------------------------------------------------------------------- + // Receive request from the client. + //----------------------------------------------------------------------------- + socket.Close(); + + return 1; +} diff --git a/examples/ThirdPartyLibs/clsocket/ReleaseNotes b/examples/ThirdPartyLibs/clsocket/ReleaseNotes new file mode 100644 index 000000000..8e567f616 --- /dev/null +++ b/examples/ThirdPartyLibs/clsocket/ReleaseNotes @@ -0,0 +1,479 @@ +=============================================================================== +Release v1.4.1 +=============================================================================== + +I. New Features +--------------- + * New methods: + CSimpleSocket::EnableNagleAlgorithm() + CSimpleSocket::DisableNagleAlgorithm() + +II. Deprecated Functionality +---------------------------- + +III. Bug Fixes +-------------- + + Reported Bugs + ------------- + #95 - Add support to enable/disable Nable algorithm + #131 - Multicast receiver not working + + Unreported Bugs + --------------- + +IV. Known Issues +---------------- + #44 - Add MTU size test to unit test so fragmentation can be tested. + #45 - Test Select() with Recv() and Send() set as non-blocking. + #47 - Mechanism to setting/setting socket options/flags. + #48 - Finish support for RAW sockets. + #50 - Add IPV6 support + +V. Configuration Changes +------------------------ + +VI. Release Tag Dependencies +---------------------------- + +VII. Errata +----------- + + Bug Fixes + ------------- + +VIII. Documentation Changes +---------------------------- + + +=============================================================================== +Release v1.4.0 +=============================================================================== + +I. New Features +--------------- + * Support for multicast + * New methods: + CPassiveSocket::BindMulticast() + CSimpleSocket::SetMulticast() + CSimpleSocket::GetMulticast() + + +II. Deprecated Functionality +---------------------------- + +III. Bug Fixes +-------------- + + Reported Bugs + ------------- + #92 - Add multicast to library + + Unreported Bugs + --------------- + +IV. Known Issues +---------------- + #44 - Add MTU size test to unit test so fragmentation can be tested. + #45 - Test Select() with Recv() and Send() set as non-blocking. + #47 - Mechanism to setting/setting socket options/flags. + #48 - Finish support for RAW sockets. + #50 - Add IPV6 support + +V. Configuration Changes +------------------------ + +VI. Release Tag Dependencies +---------------------------- + +VII. Errata +----------- + + Bug Fixes + ------------- + +VIII. Documentation Changes +---------------------------- + + +=============================================================================== +Release v1.3.3 +=============================================================================== + +I. New Features +--------------- + * Now compiles for Macintosh - DMG file not yet supported + * New method CSimpleSocket::Shutdown() - used to control + shutdown on socket. + +II. Deprecated Functionality +---------------------------- + +III. Bug Fixes +-------------- + + Reported Bugs + ------------- + #49 - Support for Macintosh + #86 - Create new method to control shutdown of socket + #87 - Memory leak detected + + Unreported Bugs + --------------- + +IV. Known Issues +---------------- + #44 - Add MTU size test to unit test so fragmentation can be tested. + #45 - Test Select() with Recv() and Send() set as non-blocking. + #47 - Mechanism to setting/setting socket options/flags. + #48 - Finish support for RAW sockets. + #50 - Add IPV6 support + +V. Configuration Changes +------------------------ + +VI. Release Tag Dependencies +---------------------------- + +VII. Errata +----------- + + Bug Fixes + ------------- + +VIII. Documentation Changes +---------------------------- + + +=============================================================================== +Release v1.3.2 +=============================================================================== + +I. New Features +--------------- + +II. Deprecated Functionality +---------------------------- + +III. Bug Fixes +-------------- + + Reported Bugs + ------------- + #84 - CActiveSocket::Close() shutsdown both sides of the socket + + Unreported Bugs + --------------- + +IV. Known Issues +---------------- + #44 - Add MTU size test to unit test so fragmentation can be tested. + #45 - Test Select() with Recv() and Send() set as non-blocking. + #47 - Mechanism to setting/setting socket options/flags. + #48 - Finish support for RAW sockets. + #49 - Support for Macintosh. + #50 - Add IPV6 support + +V. Configuration Changes +------------------------ + +VI. Release Tag Dependencies +---------------------------- + +VII. Errata +----------- + + Bug Fixes + ------------- + +VIII. Documentation Changes +---------------------------- + + +=============================================================================== +Release v1.3.1 +=============================================================================== + +I. New Features +--------------- +* New methods: + SetOptionLinger() - Enable/disable linger option. + SetOptionReuseAddr() - Set option reuse port. +* SimpleSocket::Receive() will only allocate a buffer if the internal buffer + is NULL or the buffer size is not equal to the previously allocated + buffer. + +II. Deprecated Functionality +---------------------------- + +III. Bug Fixes +-------------- + + Reported Bugs + ------------- + #64 - Method GetClientPort() returns value in byte swapped order + #83 - WIN32 SetBlocking() is broke. + + Unreported Bugs + --------------- + +IV. Known Issues +---------------- + #44 - Add MTU size test to unit test so fragmentation can be tested. + #45 - Test Select() with Recv() and Send() set as non-blocking. + #47 - Mechanism to setting/setting socket options/flags. + #48 - Finish support for RAW sockets. + #49 - Support for Macintosh. + #50 - Add IPV6 support + +V. Configuration Changes +------------------------ + +VI. Release Tag Dependencies +---------------------------- + +VII. Errata +----------- + + Bug Fixes + ------------- + +VIII. Documentation Changes +---------------------------- + + + +=============================================================================== +Release v1.3.0 +=============================================================================== + +I. New Features +--------------- +* New methods: + SendVector() - implements the iovec functionality on both linux and + Windows. + SetSendWindowSize() - Sent the TCP window size for send. + SetReceiveWindowSize() - Set the TCP windows size for receive. + GetSendWindowSize() - Get the TCP window size for send. + GetReceiveWindowSize() - Get the TCP window size fo receive. + Select(int sec, int usec) - Overloaded function to specify timeout + value of select. + +II. Deprecated Functionality +---------------------------- + +III. Bug Fixes +-------------- + + Reported Bugs + ------------- + #33 - Add SendVector mehtod to class + #41 - Sockets library MUST be signal safe + #51 - Add support to set TCP windows size + #52 - Select closes socket if timeout occurs + #53 - UDP receive always fails even when successful + + Unreported Bugs + --------------- + +IV. Known Issues +---------------- + #44 - Add MTU size test to unit test so fragmentation can be tested. + #45 - Test Select() with Recv() and Send() set as non-blocking. + #47 - Mechanism to setting/setting socket options/flags. + #48 - Finish support for RAW sockets. + #49 - Support for Macintosh. + #50 - Add IPV6 support + +V. Configuration Changes +------------------------ + +VI. Release Tag Dependencies +---------------------------- + +VII. Errata +----------- + + Bug Fixes + ------------- + +VIII. Documentation Changes +---------------------------- + + + + +=============================================================================== +Release v1.2.0 +=============================================================================== + +I. New Features +--------------- +* New method SetSocketDscp() and GetSocketDscp() for setting and getting DSCP values. + +II. Deprecated Functionality +---------------------------- + +III. Bug Fixes +-------------- + + Reported Bugs + ------------- + #17 - Finish documentation of library + #34 - Add SendFile() method to class + #37 - Make new methods GetServerAddress() and GetClientAddress() + + Unreported Bugs + --------------- + +IV. Known Issues +---------------- + #41 - Sockets library MUST be signal safe + #44 - Add MTU size test to unit test so fragmentation can be tested. + #45 - Test Select() with Recv() and Send() set as non-blocking. + #47 - Mechanism to setting/setting socket options/flags + +V. Configuration Changes +------------------------ + +VI. Release Tag Dependencies +---------------------------- + +VII. Errata +----------- + + Bug Fixes + ------------- + +VIII. Documentation Changes +---------------------------- + + + +=============================================================================== +Release v1.1.0 +=============================================================================== + +I. New Features +--------------- + * UDP Now supported + +II. Deprecated Functionality +---------------------------- +* SetSocketExpedited() method. + +III. Bug Fixes +-------------- + + Reported Bugs + ------------- + #18 - Compile under windows + #24 - Add more type and error checking to CSocket + #29 - Add UDP support + #35 - unit testing of socket library causes crash on windows + + Unreported Bugs + --------------- + +IV. Known Issues +---------------- + +V. Configuration Changes +------------------------ + +VI. Release Tag Dependencies +---------------------------- + +VII. Errata +----------- + + Bug Fixes + ------------- + +VIII. Documentation Changes +---------------------------- + + + +=============================================================================== +Release v1.0.3 +=============================================================================== + +I. New Features +--------------- + * New method SetSocketExpedited() for setting expedited traffice (DSCP settings). + +II. Deprecated Functionality +---------------------------- + +III. Bug Fixes +-------------- + + Reported Bugs + ------------- + #27 - Finish adding stats code to CSocket class. + #30 - ConnectTCP() does not return correct error for inavlid IP Address. + + Unreported Bugs + --------------- + +IV. Known Issues +---------------- + +V. Configuration Changes +------------------------ + +VI. Release Tag Dependencies +---------------------------- + +VII. Errata +----------- + + Bug Fixes + ------------- + +VIII. Documentation Changes +---------------------------- + + + +=============================================================================== +Release v1.0.2 +=============================================================================== + +I. New Features +--------------- +* Implemented a new socket mode "CSocketMode::Passive" which allows the creation + of a listening socket. Two new methods are available to control behavior for + the listening socket: Listen() and Accept(). + +II. Deprecated Functionality +---------------------------- + +III. Bug Fixes +-------------- + #23 - Create Listen() method + + Reported Bugs + ------------- + + Unreported Bugs + --------------- + +IV. Known Issues +---------------- + +V. Configuration Changes +------------------------ + +VI. Release Tag Dependencies +---------------------------- + +VII. Errata +----------- + + Bug Fixes + ------------- + +VIII. Documentation Changes +---------------------------- diff --git a/examples/ThirdPartyLibs/clsocket/src/ActiveSocket.cpp b/examples/ThirdPartyLibs/clsocket/src/ActiveSocket.cpp new file mode 100644 index 000000000..3dd5b12e1 --- /dev/null +++ b/examples/ThirdPartyLibs/clsocket/src/ActiveSocket.cpp @@ -0,0 +1,310 @@ +/*---------------------------------------------------------------------------*/ +/* */ +/* CActiveSocket.cpp - Active Socket Implementation */ +/* */ +/* Author : Mark Carrier (mark@carrierlabs.com) */ +/* */ +/*---------------------------------------------------------------------------*/ +/* Copyright (c) 2007-2009 CarrierLabs, LLC. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. The name "CarrierLabs" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * mark@carrierlabs.com. + * + * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + *----------------------------------------------------------------------------*/ +#include "ActiveSocket.h" + +CActiveSocket::CActiveSocket(CSocketType nType) : CSimpleSocket(nType) +{ +} + +//------------------------------------------------------------------------------ +// +// ConnectTCP() - +// +//------------------------------------------------------------------------------ +bool CActiveSocket::ConnectTCP(const char *pAddr, uint16 nPort) +{ + bool bRetVal = false; + struct in_addr stIpAddress; + + //------------------------------------------------------------------ + // Preconnection setup that must be preformed + //------------------------------------------------------------------ + memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr)); + m_stServerSockaddr.sin_family = AF_INET; + + if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL) + { +#ifdef WIN32 + TranslateSocketError(); +#else + if (h_errno == HOST_NOT_FOUND) + { + SetSocketError(SocketInvalidAddress); + } +#endif + return bRetVal; + } + + memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length); + m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr; + + if ((int32)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError) + { + TranslateSocketError(); + return bRetVal; + } + + m_stServerSockaddr.sin_port = htons(nPort); + + //------------------------------------------------------------------ + // Connect to address "xxx.xxx.xxx.xxx" (IPv4) address only. + // + //------------------------------------------------------------------ + m_timer.Initialize(); + m_timer.SetStartTime(); + + if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) == + CSimpleSocket::SocketError) + { + //-------------------------------------------------------------- + // Get error value this might be a non-blocking socket so we + // must first check. + //-------------------------------------------------------------- + TranslateSocketError(); + + //-------------------------------------------------------------- + // If the socket is non-blocking and the current socket error + // is SocketEinprogress or SocketEwouldblock then poll connection + // with select for designated timeout period. + // Linux returns EINPROGRESS and Windows returns WSAEWOULDBLOCK. + //-------------------------------------------------------------- + if ((IsNonblocking()) && + ((GetSocketError() == CSimpleSocket::SocketEwouldblock) || + (GetSocketError() == CSimpleSocket::SocketEinprogress))) + { + bRetVal = Select(GetConnectTimeoutSec(), GetConnectTimeoutUSec()); + } + } + else + { + TranslateSocketError(); + bRetVal = true; + } + + m_timer.SetEndTime(); + + return bRetVal; +} + +//------------------------------------------------------------------------------ +// +// ConnectUDP() - +// +//------------------------------------------------------------------------------ +bool CActiveSocket::ConnectUDP(const char *pAddr, uint16 nPort) +{ + bool bRetVal = false; + struct in_addr stIpAddress; + + //------------------------------------------------------------------ + // Pre-connection setup that must be preformed + //------------------------------------------------------------------ + memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr)); + m_stServerSockaddr.sin_family = AF_INET; + + if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL) + { +#ifdef WIN32 + TranslateSocketError(); +#else + if (h_errno == HOST_NOT_FOUND) + { + SetSocketError(SocketInvalidAddress); + } +#endif + return bRetVal; + } + + memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length); + m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr; + + if ((int32)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError) + { + TranslateSocketError(); + return bRetVal; + } + + m_stServerSockaddr.sin_port = htons(nPort); + + //------------------------------------------------------------------ + // Connect to address "xxx.xxx.xxx.xxx" (IPv4) address only. + // + //------------------------------------------------------------------ + m_timer.Initialize(); + m_timer.SetStartTime(); + + if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != CSimpleSocket::SocketError) + { + bRetVal = true; + } + + TranslateSocketError(); + + m_timer.SetEndTime(); + + return bRetVal; +} + +//------------------------------------------------------------------------------ +// +// ConnectRAW() - +// +//------------------------------------------------------------------------------ +bool CActiveSocket::ConnectRAW(const char *pAddr, uint16 nPort) +{ + bool bRetVal = false; + struct in_addr stIpAddress; + //------------------------------------------------------------------ + // Pre-connection setup that must be preformed + //------------------------------------------------------------------ + memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr)); + m_stServerSockaddr.sin_family = AF_INET; + + if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL) + { +#ifdef WIN32 + TranslateSocketError(); +#else + if (h_errno == HOST_NOT_FOUND) + { + SetSocketError(SocketInvalidAddress); + } +#endif + return bRetVal; + } + + memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length); + m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr; + + if ((int32)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError) + { + TranslateSocketError(); + return bRetVal; + } + + m_stServerSockaddr.sin_port = htons(nPort); + + //------------------------------------------------------------------ + // Connect to address "xxx.xxx.xxx.xxx" (IPv4) address only. + // + //------------------------------------------------------------------ + m_timer.Initialize(); + m_timer.SetStartTime(); + + if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != CSimpleSocket::SocketError) + { + bRetVal = true; + } + + TranslateSocketError(); + + m_timer.SetEndTime(); + + return bRetVal; +} + + +//------------------------------------------------------------------------------ +// +// Open() - Create a connection to a specified address on a specified port +// +//------------------------------------------------------------------------------ +bool CActiveSocket::Open(const char *pAddr, uint16 nPort) +{ + bool bRetVal = false; + + if (IsSocketValid() == false) + { + SetSocketError(CSimpleSocket::SocketInvalidSocket); + return bRetVal; + } + + if (pAddr == NULL) + { + SetSocketError(CSimpleSocket::SocketInvalidAddress); + return bRetVal; + } + + if (nPort == 0) + { + SetSocketError(CSimpleSocket::SocketInvalidPort); + return bRetVal; + } + + switch (m_nSocketType) + { + case CSimpleSocket::SocketTypeTcp : + { + bRetVal = ConnectTCP(pAddr, nPort); + break; + } + case CSimpleSocket::SocketTypeUdp : + { + bRetVal = ConnectUDP(pAddr, nPort); + break; + } + case CSimpleSocket::SocketTypeRaw : + break; + default: + break; + } + + //-------------------------------------------------------------------------- + // If successful then create a local copy of the address and port + //-------------------------------------------------------------------------- + if (bRetVal) + { + socklen_t nSockLen = sizeof(struct sockaddr); + + memset(&m_stServerSockaddr, 0, nSockLen); + getpeername(m_socket, (struct sockaddr *)&m_stServerSockaddr, &nSockLen); + + nSockLen = sizeof(struct sockaddr); + memset(&m_stClientSockaddr, 0, nSockLen); + getsockname(m_socket, (struct sockaddr *)&m_stClientSockaddr, &nSockLen); + + SetSocketError(SocketSuccess); + } + + return bRetVal; +} diff --git a/examples/ThirdPartyLibs/clsocket/src/ActiveSocket.h b/examples/ThirdPartyLibs/clsocket/src/ActiveSocket.h new file mode 100644 index 000000000..e452098a7 --- /dev/null +++ b/examples/ThirdPartyLibs/clsocket/src/ActiveSocket.h @@ -0,0 +1,91 @@ +/*---------------------------------------------------------------------------*/ +/* */ +/* ActiveSocket.h - Active Socket Decleration */ +/* */ +/* Author : Mark Carrier (mark@carrierlabs.com) */ +/* */ +/*---------------------------------------------------------------------------*/ +/* Copyright (c) 2007-2009 CarrierLabs, LLC. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. The name "CarrierLabs" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * mark@carrierlabs.com. + * + * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + *----------------------------------------------------------------------------*/ +#ifndef __ACTIVESOCKET_H__ +#define __ACTIVESOCKET_H__ + +#include "SimpleSocket.h" + +class CPassiveSocket; + +/// Provides a platform independent class to create an active socket. +/// An active socket is used to create a socket which connects to a server. +/// This type of object would be used when an application needs to send/receive +/// data from a server. +class CActiveSocket : public CSimpleSocket { +public: + friend class CPassiveSocket; + + CActiveSocket(CSocketType type = SocketTypeTcp); + virtual ~CActiveSocket() { + Close(); + }; + + /// Established a connection to the address specified by pAddr. + /// Connection-based protocol sockets (CSocket::SocketTypeTcp) may + /// successfully call Open() only once, however; connectionless protocol + /// sockets (CSocket::SocketTypeUdp) may use Open() multiple times to + /// change their association. + /// @param pAddr specifies the destination address to connect. + /// @param nPort specifies the destination port. + /// @return true if successful connection made, otherwise false. + virtual bool Open(const char *pAddr, uint16 nPort); + +private: + /// Utility function used to create a TCP connection, called from Open(). + /// @return true if successful connection made, otherwise false. + bool ConnectTCP(const char *pAddr, uint16 nPort); + + /// Utility function used to create a UDP connection, called from Open(). + /// @return true if successful connection made, otherwise false. + bool ConnectUDP(const char *pAddr, uint16 nPort); + + /// Utility function used to create a RAW connection, called from Open(). + /// @return true if successful connection made, otherwise false. + bool ConnectRAW(const char *pAddr, uint16 nPort); + +private: + struct hostent *m_pHE; +}; + +#endif /* __ACTIVESOCKET_H__ */ + diff --git a/examples/ThirdPartyLibs/clsocket/src/Host.h b/examples/ThirdPartyLibs/clsocket/src/Host.h new file mode 100644 index 000000000..9eaaba1d9 --- /dev/null +++ b/examples/ThirdPartyLibs/clsocket/src/Host.h @@ -0,0 +1,257 @@ +/*---------------------------------------------------------------------------*/ +/* */ +/* Host.h - Basic header file to provide cross-platform solutions via */ +/* macros, conditional compilation, etc. */ +/* */ +/* Author : Mark Carrier (mark@carrierlabs.com) */ +/* */ +/*---------------------------------------------------------------------------*/ +/* Copyright (c) 2007 CarrierLabs, LLC. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. The name "CarrierLabs" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * mark@carrierlabs.com. + * + * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + *----------------------------------------------------------------------------*/ +#ifndef __HOST_H__ +#define __HOST_H__ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*---------------------------------------------------------------------------*/ +/* */ +/* Type Definition Macros */ +/* */ +/*---------------------------------------------------------------------------*/ +#ifndef __WORDSIZE + /* Assume 32 */ + #define __WORDSIZE 32 +#endif + +#if defined(_LINUX) || defined(_DARWIN) + typedef unsigned char uint8; + typedef char int8; + typedef unsigned short uint16; + typedef short int16; + typedef unsigned int uint32; + typedef int int32; + typedef int SOCKET; +#endif + +#ifdef WIN32 + struct iovec { + void *iov_base; + size_t iov_len; + }; + + typedef unsigned char uint8; + typedef char int8; + typedef unsigned short uint16; + typedef short int16; + typedef unsigned int uint32; + typedef int int32; +#endif + +#ifdef WIN32 + typedef int socklen_t; +#endif + +#if defined(WIN32) + typedef unsigned long long int uint64; + typedef long long int int64; +#elif (__WORDSIZE == 32) + __extension__ + typedef long long int int64; + __extension__ + typedef unsigned long long int uint64; +#elif (__WORDSIZE == 64) + typedef unsigned long int uint64; + typedef long int int64; +#endif + +#ifdef WIN32 + + #ifndef UINT8_MAX + #define UINT8_MAX (UCHAR_MAX) + #endif + #ifndef UINT16_MAX + #define UINT16_MAX (USHRT_MAX) + #endif + #ifndef UINT32_MAX + #define UINT32_MAX (ULONG_MAX) + #endif + + #if __WORDSIZE == 64 + #define SIZE_MAX (18446744073709551615UL) + #else + #ifndef SIZE_MAX + #define SIZE_MAX (4294967295U) + #endif + #endif +#endif + +#if defined(WIN32) + #define ssize_t size_t +#endif + +#ifndef TRUE + #define TRUE 1 +#endif + +#ifndef FALSE + #define FALSE 0 +#endif + +#ifndef htonll +#ifdef _BIG_ENDIAN +#define htonll(x) (x) +#define ntohll(x) (x) +#else +#define htonll(x) ((((uint64)htonl(x)) << 32) + htonl(x >> 32)) +#define ntohll(x) ((((uint64)ntohl(x)) << 32) + ntohl(x >> 32)) +#endif +#endif + +/*---------------------------------------------------------------------------*/ +/* */ +/* Socket Macros */ +/* */ +/*---------------------------------------------------------------------------*/ +#ifdef WIN32 +#define SHUT_RD 0 +#define SHUT_WR 1 +#define SHUT_RDWR 2 +#define ACCEPT(a,b,c) accept(a,b,c) +#define CONNECT(a,b,c) connect(a,b,c) +#define CLOSE(a) closesocket(a) +#define READ(a,b,c) read(a,b,c) +#define RECV(a,b,c,d) recv(a, (char *)b, c, d) +#define RECVFROM(a,b,c,d,e,f) recvfrom(a, (char *)b, c, d, (sockaddr *)e, (int *)f) +#define RECV_FLAGS MSG_WAITALL +#define SELECT(a,b,c,d,e) select((int32)a,b,c,d,e) +#define SEND(a,b,c,d) send(a, (const char *)b, (int)c, d) +#define SENDTO(a,b,c,d,e,f) sendto(a, (const char *)b, (int)c, d, e, f) +#define SEND_FLAGS 0 +#define SENDFILE(a,b,c,d) sendfile(a, b, c, d) +#define SET_SOCKET_ERROR(x,y) errno=y +#define SOCKET_ERROR_INTERUPT EINTR +#define SOCKET_ERROR_TIMEDOUT EAGAIN +#define WRITE(a,b,c) write(a,b,c) +#define WRITEV(a,b,c) Writev(b, c) +#define GETSOCKOPT(a,b,c,d,e) getsockopt(a,b,c,(char *)d, (int *)e) +#define SETSOCKOPT(a,b,c,d,e) setsockopt(a,b,c,(char *)d, (int)e) +#define GETHOSTBYNAME(a) gethostbyname(a) +#endif + +#if defined(_LINUX) || defined(_DARWIN) +#define ACCEPT(a,b,c) accept(a,b,c) +#define CONNECT(a,b,c) connect(a,b,c) +#define CLOSE(a) close(a) +#define READ(a,b,c) read(a,b,c) +#define RECV(a,b,c,d) recv(a, (void *)b, c, d) +#define RECVFROM(a,b,c,d,e,f) recvfrom(a, (char *)b, c, d, (sockaddr *)e, f) +#define RECV_FLAGS MSG_WAITALL +#define SELECT(a,b,c,d,e) select(a,b,c,d,e) +#define SEND(a,b,c,d) send(a, (const int8 *)b, c, d) +#define SENDTO(a,b,c,d,e,f) sendto(a, (const int8 *)b, c, d, e, f) +#define SEND_FLAGS 0 +#define SENDFILE(a,b,c,d) sendfile(a, b, c, d) +#define SET_SOCKET_ERROR(x,y) errno=y +#define SOCKET_ERROR_INTERUPT EINTR +#define SOCKET_ERROR_TIMEDOUT EAGAIN +#define WRITE(a,b,c) write(a,b,c) +#define WRITEV(a,b,c) writev(a, b, c) +#define GETSOCKOPT(a,b,c,d,e) getsockopt((int)a,(int)b,(int)c,(void *)d,(socklen_t *)e) +#define SETSOCKOPT(a,b,c,d,e) setsockopt((int)a,(int)b,(int)c,(const void *)d,(int)e) +#define GETHOSTBYNAME(a) gethostbyname(a) +#endif + + +/*---------------------------------------------------------------------------*/ +/* */ +/* File Macros */ +/* */ +/*---------------------------------------------------------------------------*/ +#define STRUCT_STAT struct stat +#define LSTAT(x,y) lstat(x,y) +#define FILE_HANDLE FILE * +#define CLEARERR(x) clearerr(x) +#define FCLOSE(x) fclose(x) +#define FEOF(x) feof(x) +#define FERROR(x) ferror(x) +#define FFLUSH(x) fflush(x) +#define FILENO(s) fileno(s) +#define FOPEN(x,y) fopen(x, y) + //#define FREAD(a,b,c,d) fread(a, b, c, d) +#define FSTAT(s, st) fstat(FILENO(s), st) + //#define FWRITE(a,b,c,d) fwrite(a, b, c, d) +#define STAT_BLK_SIZE(x) ((x).st_blksize) + + +/*---------------------------------------------------------------------------*/ +/* */ +/* Misc Macros */ +/* */ +/*---------------------------------------------------------------------------*/ +#if defined(WIN32) + #define GET_CLOCK_COUNT(x) QueryPerformanceCounter((LARGE_INTEGER *)x) +#else + #define GET_CLOCK_COUNT(x) gettimeofday(x, NULL) +#endif + +#if defined(WIN32) + #define STRTOULL(x) _atoi64(x) +#else + #define STRTOULL(x) strtoull(x, NULL, 10) +#endif + +#if defined(WIN32) + #define SNPRINTF _snprintf + #define PRINTF printf + #define VPRINTF vprintf + #define FPRINTF fprintf +#else + #define SNPRINTF snprintf + #define PRINTF printf + #define VPRINTF vprintf + #define FPRINTF fprintf +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __HOST_H__ */ diff --git a/examples/ThirdPartyLibs/clsocket/src/PassiveSocket.cpp b/examples/ThirdPartyLibs/clsocket/src/PassiveSocket.cpp new file mode 100644 index 000000000..e792fe149 --- /dev/null +++ b/examples/ThirdPartyLibs/clsocket/src/PassiveSocket.cpp @@ -0,0 +1,331 @@ +/*---------------------------------------------------------------------------*/ +/* */ +/* PassiveSocket.cpp - Passive Socket Implementation */ +/* */ +/* Author : Mark Carrier (mark@carrierlabs.com) */ +/* */ +/*---------------------------------------------------------------------------*/ +/* Copyright (c) 2007-2009 CarrierLabs, LLC. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. The name "CarrierLabs" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * mark@carrierlabs.com. + * + * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + *----------------------------------------------------------------------------*/ +#include "PassiveSocket.h" + + + +CPassiveSocket::CPassiveSocket(CSocketType nType) : CSimpleSocket(nType) +{ +} + +bool CPassiveSocket::BindMulticast(const char *pInterface, const char *pGroup, uint16 nPort) +{ + bool bRetVal = false; +#ifdef WIN32 + ULONG inAddr; +#else + int32 nReuse; + in_addr_t inAddr; + + nReuse = IPTOS_LOWDELAY; +#endif + + //-------------------------------------------------------------------------- + // Set the following socket option SO_REUSEADDR. This will allow the file + // descriptor to be reused immediately after the socket is closed instead + // of setting in a TIMED_WAIT state. + //-------------------------------------------------------------------------- + memset(&m_stMulticastGroup,0,sizeof(m_stMulticastGroup)); + m_stMulticastGroup.sin_family = AF_INET; + m_stMulticastGroup.sin_port = htons(nPort); + + //-------------------------------------------------------------------------- + // If no IP Address (interface ethn) is supplied, or the loop back is + // specified then bind to any interface, else bind to specified interface. + //-------------------------------------------------------------------------- + if ((pInterface == NULL) || (!strlen(pInterface))) + { + m_stMulticastGroup.sin_addr.s_addr = htonl(INADDR_ANY); + } + else + { + if ((inAddr = inet_addr(pInterface)) != INADDR_NONE) + { + m_stMulticastGroup.sin_addr.s_addr = inAddr; + } + } + + //-------------------------------------------------------------------------- + // Bind to the specified port + //-------------------------------------------------------------------------- + if (bind(m_socket, (struct sockaddr *)&m_stMulticastGroup, sizeof(m_stMulticastGroup)) == 0) + { + //---------------------------------------------------------------------- + // Join the multicast group + //---------------------------------------------------------------------- + m_stMulticastRequest.imr_multiaddr.s_addr = inet_addr(pGroup); + m_stMulticastRequest.imr_interface.s_addr = m_stMulticastGroup.sin_addr.s_addr; + + if (SETSOCKOPT(m_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, + (void *)&m_stMulticastRequest, + sizeof(m_stMulticastRequest)) == CSimpleSocket::SocketSuccess) + { + bRetVal = true; + } + + m_timer.SetEndTime(); + } + + m_timer.Initialize(); + m_timer.SetStartTime(); + + + //-------------------------------------------------------------------------- + // If there was a socket error then close the socket to clean out the + // connection in the backlog. + //-------------------------------------------------------------------------- + TranslateSocketError(); + + if (bRetVal == false) + { + Close(); + } + + return bRetVal; +} + + +//------------------------------------------------------------------------------ +// +// Listen() - +// +//------------------------------------------------------------------------------ +bool CPassiveSocket::Listen(const char *pAddr, uint16 nPort, int32 nConnectionBacklog) +{ + bool bRetVal = false; +#ifdef WIN32 + ULONG inAddr; +#else + int32 nReuse; + in_addr_t inAddr; + + nReuse = IPTOS_LOWDELAY; +#endif + + //-------------------------------------------------------------------------- + // Set the following socket option SO_REUSEADDR. This will allow the file + // descriptor to be reused immediately after the socket is closed instead + // of setting in a TIMED_WAIT state. + //-------------------------------------------------------------------------- +#ifdef _LINUX + SETSOCKOPT(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&nReuse, sizeof(int32)); + SETSOCKOPT(m_socket, IPPROTO_TCP, IP_TOS, &nReuse, sizeof(int32)); +#endif + + memset(&m_stServerSockaddr,0,sizeof(m_stServerSockaddr)); + m_stServerSockaddr.sin_family = AF_INET; + m_stServerSockaddr.sin_port = htons(nPort); + + //-------------------------------------------------------------------------- + // If no IP Address (interface ethn) is supplied, or the loop back is + // specified then bind to any interface, else bind to specified interface. + //-------------------------------------------------------------------------- + if ((pAddr == NULL) || (!strlen(pAddr))) + { + m_stServerSockaddr.sin_addr.s_addr = htonl(INADDR_ANY); + } + else + { + if ((inAddr = inet_addr(pAddr)) != INADDR_NONE) + { + m_stServerSockaddr.sin_addr.s_addr = inAddr; + } + } + + m_timer.Initialize(); + m_timer.SetStartTime(); + + //-------------------------------------------------------------------------- + // Bind to the specified port + //-------------------------------------------------------------------------- + if (bind(m_socket, (struct sockaddr *)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != CSimpleSocket::SocketError) + { + if (m_nSocketType == CSimpleSocket::SocketTypeTcp) + { + if (listen(m_socket, nConnectionBacklog) != CSimpleSocket::SocketError) + { + bRetVal = true; + } + } + else + { + bRetVal = true; + } + } + + m_timer.SetEndTime(); + + //-------------------------------------------------------------------------- + // If there was a socket error then close the socket to clean out the + // connection in the backlog. + //-------------------------------------------------------------------------- + TranslateSocketError(); + + if (bRetVal == false) + { + Close(); + } + + return bRetVal; +} + + +//------------------------------------------------------------------------------ +// +// Accept() - +// +//------------------------------------------------------------------------------ +CActiveSocket *CPassiveSocket::Accept() +{ + uint32 nSockLen; + CActiveSocket *pClientSocket = NULL; + SOCKET socket = CSimpleSocket::SocketError; + + if (m_nSocketType != CSimpleSocket::SocketTypeTcp) + { + SetSocketError(CSimpleSocket::SocketProtocolError); + return pClientSocket; + } + + pClientSocket = new CActiveSocket(); + + //-------------------------------------------------------------------------- + // Wait for incoming connection. + //-------------------------------------------------------------------------- + if (pClientSocket != NULL) + { + CSocketError socketErrno = SocketSuccess; + + m_timer.Initialize(); + m_timer.SetStartTime(); + + nSockLen = sizeof(m_stClientSockaddr); + + do + { + errno = 0; + socket = accept(m_socket, (struct sockaddr *)&m_stClientSockaddr, (socklen_t *)&nSockLen); + + if (socket != -1) + { + pClientSocket->SetSocketHandle(socket); + pClientSocket->TranslateSocketError(); + socketErrno = pClientSocket->GetSocketError(); + socklen_t nSockLen = sizeof(struct sockaddr); + + //------------------------------------------------------------- + // Store client and server IP and port information for this + // connection. + //------------------------------------------------------------- + getpeername(m_socket, (struct sockaddr *)&pClientSocket->m_stClientSockaddr, &nSockLen); + memcpy((void *)&pClientSocket->m_stClientSockaddr, (void *)&m_stClientSockaddr, nSockLen); + + memset(&pClientSocket->m_stServerSockaddr, 0, nSockLen); + getsockname(m_socket, (struct sockaddr *)&pClientSocket->m_stServerSockaddr, &nSockLen); + } + else + { + TranslateSocketError(); + socketErrno = GetSocketError(); + } + + } while (socketErrno == CSimpleSocket::SocketInterrupted); + + m_timer.SetEndTime(); + + if (socketErrno != CSimpleSocket::SocketSuccess) + { + delete pClientSocket; + pClientSocket = NULL; + } + } + + return pClientSocket; +} + + +//------------------------------------------------------------------------------ +// +// Send() - Send data on a valid socket +// +//------------------------------------------------------------------------------ +int32 CPassiveSocket::Send(const uint8 *pBuf, size_t bytesToSend) +{ + SetSocketError(SocketSuccess); + m_nBytesSent = 0; + + switch(m_nSocketType) + { + case CSimpleSocket::SocketTypeUdp: + { + if (IsSocketValid()) + { + if ((bytesToSend > 0) && (pBuf != NULL)) + { + m_timer.Initialize(); + m_timer.SetStartTime(); + + m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0, + (const sockaddr *)&m_stClientSockaddr, + sizeof(m_stClientSockaddr)); + + m_timer.SetEndTime(); + + if (m_nBytesSent == CSimpleSocket::SocketError) + { + TranslateSocketError(); + } + } + } + break; + } + case CSimpleSocket::SocketTypeTcp: + CSimpleSocket::Send(pBuf, bytesToSend); + break; + default: + SetSocketError(SocketProtocolError); + break; + } + + return m_nBytesSent; +} diff --git a/examples/ThirdPartyLibs/clsocket/src/PassiveSocket.h b/examples/ThirdPartyLibs/clsocket/src/PassiveSocket.h new file mode 100644 index 000000000..a5f4fd135 --- /dev/null +++ b/examples/ThirdPartyLibs/clsocket/src/PassiveSocket.h @@ -0,0 +1,119 @@ +/*---------------------------------------------------------------------------*/ +/* */ +/* Socket.h - Passive Socket Decleration. */ +/* */ +/* Author : Mark Carrier (mark@carrierlabs.com) */ +/* */ +/*---------------------------------------------------------------------------*/ +/* Copyright (c) 2007-2009 CarrierLabs, LLC. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. The name "CarrierLabs" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * mark@carrierlabs.com. + * + * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + *----------------------------------------------------------------------------*/ +#ifndef __PASSIVESOCKET_H__ +#define __PASSIVESOCKET_H__ +#include "ActiveSocket.h" + +/// Provides a platform independent class to create a passive socket. +/// A passive socket is used to create a "listening" socket. This type +/// of object would be used when an application needs to wait for +/// inbound connections. Support for CSimpleSocket::SocketTypeTcp, +/// CSimpleSocket::SocketTypeUdp, and CSimpleSocket::SocketTypeRaw is handled +/// in a similar fashion. The big difference is that the method +/// CPassiveSocket::Accept should not be called on the latter two socket +/// types. +class CPassiveSocket : public CSimpleSocket { +public: + CPassiveSocket(CSocketType type = SocketTypeTcp); + virtual ~CPassiveSocket() { + Close(); + }; + + /// Extracts the first connection request on the queue of pending + /// connections and creates a newly connected socket. Used with + /// CSocketType CSimpleSocket::SocketTypeTcp. It is the responsibility of + /// the caller to delete the returned object when finished. + /// @return if successful a pointer to a newly created CActiveSocket object + /// will be returned and the internal error condition of the CPassiveSocket + /// object will be CPassiveSocket::SocketSuccess. If an error condition was encountered + /// the NULL will be returned and one of the following error conditions will be set: + /// CPassiveSocket::SocketEwouldblock, CPassiveSocket::SocketInvalidSocket, + /// CPassiveSocket::SocketConnectionAborted, CPassiveSocket::SocketInterrupted + /// CPassiveSocket::SocketProtocolError, CPassiveSocket::SocketFirewallError + virtual CActiveSocket *Accept(void); + + /// Bind to a multicast group on a specified interface, multicast group, and port + /// + /// @param pInterface - interface on which to bind. + /// @param pGroup - multicast group address to bind. + /// @param nPort - port on which multicast + /// @return true if able to bind to interface and multicast group. + /// If not successful, the false is returned and one of the following error + /// condiitions will be set: CPassiveSocket::SocketAddressInUse, CPassiveSocket::SocketProtocolError, + /// CPassiveSocket::SocketInvalidSocket. The following socket errors are for Linux/Unix + /// derived systems only: CPassiveSocket::SocketInvalidSocketBuffer + bool BindMulticast(const char *pInterface, const char *pGroup, uint16 nPort); + + /// Create a listening socket at local ip address 'x.x.x.x' or 'localhost' + /// if pAddr is NULL on port nPort. + /// + /// @param pAddr specifies the IP address on which to listen. + /// @param nPort specifies the port on which to listen. + /// @param nConnectionBacklog specifies connection queue backlog (default 30,000) + /// @return true if a listening socket was created. + /// If not successful, the false is returned and one of the following error + /// conditions will be set: CPassiveSocket::SocketAddressInUse, CPassiveSocket::SocketProtocolError, + /// CPassiveSocket::SocketInvalidSocket. The following socket errors are for Linux/Unix + /// derived systems only: CPassiveSocket::SocketInvalidSocketBuffer + virtual bool Listen(const char *pAddr, uint16 nPort, int32 nConnectionBacklog = 30000); + + /// Attempts to send a block of data on an established connection. + /// @param pBuf block of data to be sent. + /// @param bytesToSend size of data block to be sent. + /// @return number of bytes actually sent, return of zero means the + /// connection has been shutdown on the other side, and a return of -1 + /// means that an error has occurred. If an error was signaled then one + /// of the following error codes will be set: CPassiveSocket::SocketInvalidSocket, + /// CPassiveSocket::SocketEwouldblock, SimpleSocket::SocketConnectionReset, + /// CPassiveSocket::SocketInvalidSocketBuffer, CPassiveSocket::SocketInterrupted, + /// CPassiveSocket::SocketProtocolError, CPassiveSocket::SocketNotconnected + ///
\b Note: This function is used only for a socket of type + /// CSimpleSocket::SocketTypeUdp + virtual int32 Send(const uint8 *pBuf, size_t bytesToSend); + +private: + struct ip_mreq m_stMulticastRequest; /// group address for multicast + +}; + +#endif // __PASSIVESOCKET_H__ diff --git a/examples/ThirdPartyLibs/clsocket/src/SimpleSocket.cpp b/examples/ThirdPartyLibs/clsocket/src/SimpleSocket.cpp new file mode 100644 index 000000000..7bd1c8aab --- /dev/null +++ b/examples/ThirdPartyLibs/clsocket/src/SimpleSocket.cpp @@ -0,0 +1,1187 @@ +/*---------------------------------------------------------------------------*/ +/* */ +/* CSimpleSocket.cpp - CSimpleSocket Implementation */ +/* */ +/* Author : Mark Carrier (mark@carrierlabs.com) */ +/* */ +/*---------------------------------------------------------------------------*/ +/* Copyright (c) 2007-2009 CarrierLabs, LLC. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. The name "CarrierLabs" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * mark@carrierlabs.com. + * + * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + *----------------------------------------------------------------------------*/ +#include "SimpleSocket.h" + +CSimpleSocket::CSimpleSocket(CSocketType nType) : + m_socket(INVALID_SOCKET), + m_socketErrno(CSimpleSocket::SocketInvalidSocket), + m_pBuffer(NULL), m_nBufferSize(0), m_nSocketDomain(AF_INET), + m_nSocketType(SocketTypeInvalid), m_nBytesReceived(-1), + m_nBytesSent(-1), m_nFlags(0), + m_bIsBlocking(true) +{ + SetConnectTimeout(1, 0); + memset(&m_stRecvTimeout, 0, sizeof(struct timeval)); + memset(&m_stSendTimeout, 0, sizeof(struct timeval)); + memset(&m_stLinger, 0, sizeof(struct linger)); + + switch(nType) + { + //---------------------------------------------------------------------- + // Declare socket type stream - TCP + //---------------------------------------------------------------------- + case CSimpleSocket::SocketTypeTcp: + { + m_nSocketDomain = AF_INET; + m_nSocketType = CSimpleSocket::SocketTypeTcp; + break; + } + case CSimpleSocket::SocketTypeTcp6: + { + m_nSocketDomain = AF_INET6; + m_nSocketType = CSimpleSocket::SocketTypeTcp6; + break; + } + //---------------------------------------------------------------------- + // Declare socket type datagram - UDP + //---------------------------------------------------------------------- + case CSimpleSocket::SocketTypeUdp: + { + m_nSocketDomain = AF_INET; + m_nSocketType = CSimpleSocket::SocketTypeUdp; + break; + } + case CSimpleSocket::SocketTypeUdp6: + { + m_nSocketDomain = AF_INET6; + m_nSocketType = CSimpleSocket::SocketTypeUdp6; + break; + } + //---------------------------------------------------------------------- + // Declare socket type raw Ethernet - Ethernet + //---------------------------------------------------------------------- + case CSimpleSocket::SocketTypeRaw: + { +#if defined(_LINUX) && !defined(_DARWIN) + m_nSocketDomain = AF_PACKET; + m_nSocketType = CSimpleSocket::SocketTypeRaw; +#endif +#ifdef _WIN32 + m_nSocketType = CSimpleSocket::SocketTypeInvalid; +#endif + break; + } + default: + m_nSocketType = CSimpleSocket::SocketTypeInvalid; + break; + } +} + +CSimpleSocket::CSimpleSocket(CSimpleSocket &socket) +{ + m_pBuffer = new uint8[socket.m_nBufferSize]; + m_nBufferSize = socket.m_nBufferSize; + memcpy(m_pBuffer, socket.m_pBuffer, socket.m_nBufferSize); +} + +CSimpleSocket *CSimpleSocket::operator=(CSimpleSocket &socket) +{ + if (m_nBufferSize != socket.m_nBufferSize) + { + delete m_pBuffer; + m_pBuffer = new uint8[socket.m_nBufferSize]; + m_nBufferSize = socket.m_nBufferSize; + memcpy(m_pBuffer, socket.m_pBuffer, socket.m_nBufferSize); + } + + return this; +} + + +//------------------------------------------------------------------------------ +// +// Initialize() - Initialize socket class +// +//------------------------------------------------------------------------------ +bool CSimpleSocket::Initialize() +{ + errno = CSimpleSocket::SocketSuccess; + +#ifdef WIN32 + //------------------------------------------------------------------------- + // Data structure containing general Windows Sockets Info + //------------------------------------------------------------------------- + memset(&m_hWSAData, 0, sizeof(m_hWSAData)); + WSAStartup(MAKEWORD(2, 0), &m_hWSAData); +#endif + + //------------------------------------------------------------------------- + // Create the basic Socket Handle + //------------------------------------------------------------------------- + m_timer.Initialize(); + m_timer.SetStartTime(); + m_socket = socket(m_nSocketDomain, m_nSocketType, 0); + m_timer.SetEndTime(); + + TranslateSocketError(); + + return (IsSocketValid()); +} + + +//------------------------------------------------------------------------------ +// +// BindInterface() +// +//------------------------------------------------------------------------------ +bool CSimpleSocket::BindInterface(const char *pInterface) +{ + bool bRetVal = false; + struct in_addr stInterfaceAddr; + + if (GetMulticast() == true) + { + if (pInterface) + { + stInterfaceAddr.s_addr= inet_addr(pInterface); + if (SETSOCKOPT(m_socket, IPPROTO_IP, IP_MULTICAST_IF, &stInterfaceAddr, sizeof(stInterfaceAddr)) == SocketSuccess) + { + bRetVal = true; + } + } + } + else + { + SetSocketError(CSimpleSocket::SocketProtocolError); + } + + return bRetVal; +} + + +//------------------------------------------------------------------------------ +// +// SetMulticast() +// +//------------------------------------------------------------------------------ +bool CSimpleSocket::SetMulticast(bool bEnable, uint8 multicastTTL) +{ + bool bRetVal = false; + + if (GetSocketType() == CSimpleSocket::SocketTypeUdp) + { + m_bIsMulticast = bEnable; + if (SETSOCKOPT(m_socket, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&multicastTTL, sizeof(multicastTTL)) == SocketError) + { + TranslateSocketError(); + bRetVal = false; + } + else + { + bRetVal = true; + } + } + else + { + m_socketErrno = CSimpleSocket::SocketProtocolError; + } + + return bRetVal; +} + + +//------------------------------------------------------------------------------ +// +// SetSocketDscp() +// +//------------------------------------------------------------------------------ +bool CSimpleSocket::SetSocketDscp(int32 nDscp) +{ + bool bRetVal = true; + int32 nTempVal = nDscp; + + nTempVal <<= 4; + nTempVal /= 4; + + if (IsSocketValid()) + { + if (SETSOCKOPT(m_socket, IPPROTO_IP, IP_TOS, &nTempVal, sizeof(nTempVal)) == SocketError) + { + TranslateSocketError(); + bRetVal = false; + } + } + + return bRetVal; +} + + +//------------------------------------------------------------------------------ +// +// GetSocketDscp() +// +//------------------------------------------------------------------------------ +int32 CSimpleSocket::GetSocketDscp(void) +{ + int32 nTempVal = 0; + socklen_t nLen = 0; + + if (IsSocketValid()) + { + if (GETSOCKOPT(m_socket, IPPROTO_IP, IP_TOS, &nTempVal, &nLen) == SocketError) + { + TranslateSocketError(); + } + + nTempVal *= 4; + nTempVal >>= 4; + } + + return nTempVal; +} + + +//------------------------------------------------------------------------------ +// +// GetWindowSize() +// +//------------------------------------------------------------------------------ +uint32 CSimpleSocket::GetWindowSize(uint32 nOptionName) +{ + uint32 nTcpWinSize = 0; + + //------------------------------------------------------------------------- + // no socket given, return system default allocate our own new socket + //------------------------------------------------------------------------- + if (m_socket != CSimpleSocket::SocketError) + { + socklen_t nLen = sizeof(nTcpWinSize); + + //--------------------------------------------------------------------- + // query for buffer size + //--------------------------------------------------------------------- + GETSOCKOPT(m_socket, SOL_SOCKET, nOptionName, &nTcpWinSize, &nLen); + TranslateSocketError(); + } + else + { + SetSocketError(CSimpleSocket::SocketInvalidSocket); + } + + return nTcpWinSize; +} + + +//------------------------------------------------------------------------------ +// +// SetWindowSize() +// +//------------------------------------------------------------------------------ +uint32 CSimpleSocket::SetWindowSize(uint32 nOptionName, uint32 nWindowSize) +{ + uint32 nRetVal = 0; + + //------------------------------------------------------------------------- + // no socket given, return system default allocate our own new socket + //------------------------------------------------------------------------- + if (m_socket != CSimpleSocket::SocketError) + { + nRetVal = SETSOCKOPT(m_socket, SOL_SOCKET, nOptionName, &nWindowSize, sizeof(nWindowSize)); + TranslateSocketError(); + } + else + { + SetSocketError(CSimpleSocket::SocketInvalidSocket); + } + + return nWindowSize; +} + + +//------------------------------------------------------------------------------ +// +// DisableNagleAlgorithm() +// +//------------------------------------------------------------------------------ +bool CSimpleSocket::DisableNagleAlgoritm() +{ + bool bRetVal = false; + int32 nTcpNoDelay = 1; + + //---------------------------------------------------------------------- + // Set TCP NoDelay flag to true + //---------------------------------------------------------------------- + if (SETSOCKOPT(m_socket, IPPROTO_TCP, TCP_NODELAY, &nTcpNoDelay, sizeof(int32)) == 0) + { + bRetVal = true; + } + + TranslateSocketError(); + + return bRetVal; +} + + +//------------------------------------------------------------------------------ +// +// EnableNagleAlgorithm() +// +//------------------------------------------------------------------------------ +bool CSimpleSocket::EnableNagleAlgoritm() +{ + bool bRetVal = false; + int32 nTcpNoDelay = 0; + + //---------------------------------------------------------------------- + // Set TCP NoDelay flag to false + //---------------------------------------------------------------------- + if (SETSOCKOPT(m_socket, IPPROTO_TCP, TCP_NODELAY, &nTcpNoDelay, sizeof(int32)) == 0) + { + bRetVal = true; + } + + TranslateSocketError(); + + return bRetVal; +} + + +//------------------------------------------------------------------------------ +// +// Send() - Send data on a valid socket +// +//------------------------------------------------------------------------------ +int32 CSimpleSocket::Send(const uint8 *pBuf, size_t bytesToSend) +{ + SetSocketError(SocketSuccess); + m_nBytesSent = 0; + + switch(m_nSocketType) + { + case CSimpleSocket::SocketTypeTcp: + { + if (IsSocketValid()) + { + if ((bytesToSend > 0) && (pBuf != NULL)) + { + m_timer.Initialize(); + m_timer.SetStartTime(); + + //--------------------------------------------------------- + // Check error condition and attempt to resend if call + // was interrupted by a signal. + //--------------------------------------------------------- + do + { + m_nBytesSent = SEND(m_socket, pBuf, bytesToSend, 0); + TranslateSocketError(); + } while (GetSocketError() == CSimpleSocket::SocketInterrupted); + + m_timer.SetEndTime(); + } + } + break; + } + case CSimpleSocket::SocketTypeUdp: + { + if (IsSocketValid()) + { + if ((bytesToSend > 0) && (pBuf != NULL)) + { + m_timer.Initialize(); + m_timer.SetStartTime(); + + //--------------------------------------------------------- + // Check error condition and attempt to resend if call + // was interrupted by a signal. + //--------------------------------------------------------- + // if (GetMulticast()) + // { + // do + // { + // m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0, (const sockaddr *)&m_stMulticastGroup, + // sizeof(m_stMulticastGroup)); + // TranslateSocketError(); + // } while (GetSocketError() == CSimpleSocket::SocketInterrupted); + // } + // else + { + do + { + m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0, (const sockaddr *)&m_stServerSockaddr, sizeof(m_stServerSockaddr)); + TranslateSocketError(); + } while (GetSocketError() == CSimpleSocket::SocketInterrupted); + } + + m_timer.SetEndTime(); + } + } + break; + } + default: + break; + } + + return m_nBytesSent; +} + + +//------------------------------------------------------------------------------ +// +// Close() - Close socket and free up any memory allocated for the socket +// +//------------------------------------------------------------------------------ +bool CSimpleSocket::Close(void) +{ + bool bRetVal = false; + + //-------------------------------------------------------------------------- + // delete internal buffer + //-------------------------------------------------------------------------- + if (m_pBuffer != NULL) + { + delete [] m_pBuffer; + m_pBuffer = NULL; + } + + //-------------------------------------------------------------------------- + // if socket handle is currently valid, close and then invalidate + //-------------------------------------------------------------------------- + if (IsSocketValid()) + { + if (CLOSE(m_socket) != CSimpleSocket::SocketError) + { + m_socket = INVALID_SOCKET; + bRetVal = true; + } + } + + TranslateSocketError(); + + return bRetVal; +} + + +//------------------------------------------------------------------------------ +// +// Shtudown() +// +//------------------------------------------------------------------------------ +bool CSimpleSocket::Shutdown(CShutdownMode nShutdown) +{ + CSocketError nRetVal = SocketEunknown; + + nRetVal = (CSocketError)shutdown(m_socket, CSimpleSocket::Sends); + TranslateSocketError(); + + return (nRetVal == CSimpleSocket::SocketSuccess) ? true: false; +} + + +//------------------------------------------------------------------------------ +// +// Flush() +// +//------------------------------------------------------------------------------ +bool CSimpleSocket::Flush() +{ + int32 nTcpNoDelay = 1; + int32 nCurFlags = 0; + uint8 tmpbuf = 0; + bool bRetVal = false; + + //-------------------------------------------------------------------------- + // Get the current setting of the TCP_NODELAY flag. + //-------------------------------------------------------------------------- + if (GETSOCKOPT(m_socket, IPPROTO_TCP, TCP_NODELAY, &nCurFlags, sizeof(int32)) == 0) + { + //---------------------------------------------------------------------- + // Set TCP NoDelay flag + //---------------------------------------------------------------------- + if (SETSOCKOPT(m_socket, IPPROTO_TCP, TCP_NODELAY, &nTcpNoDelay, sizeof(int32)) == 0) + { + //------------------------------------------------------------------ + // Send empty byte stream to flush the TCP send buffer + //------------------------------------------------------------------ + if (Send(&tmpbuf, 0) != CSimpleSocket::SocketError) + { + bRetVal = true; + } + + TranslateSocketError(); + } + + //---------------------------------------------------------------------- + // Reset the TCP_NODELAY flag to original state. + //---------------------------------------------------------------------- + SETSOCKOPT(m_socket, IPPROTO_TCP, TCP_NODELAY, &nCurFlags, sizeof(int32)); + } + + return bRetVal; +} + + +//------------------------------------------------------------------------------ +// +// Writev - +// +//------------------------------------------------------------------------------ +int32 CSimpleSocket::Writev(const struct iovec *pVector, size_t nCount) +{ + int32 nBytes = 0; + int32 nBytesSent = 0; + int32 i = 0; + + //-------------------------------------------------------------------------- + // Send each buffer as a separate send, windows does not support this + // function call. + //-------------------------------------------------------------------------- + for (i = 0; i < (int32)nCount; i++) + { + if ((nBytes = Send((uint8 *)pVector[i].iov_base, pVector[i].iov_len)) == CSimpleSocket::SocketError) + { + break; + } + + nBytesSent += nBytes; + } + + if (i > 0) + { + Flush(); + } + + return nBytesSent; +} + + +//------------------------------------------------------------------------------ +// +// Send() - Send data on a valid socket via a vector of buffers. +// +//------------------------------------------------------------------------------ +int32 CSimpleSocket::Send(const struct iovec *sendVector, int32 nNumItems) +{ + SetSocketError(SocketSuccess); + m_nBytesSent = 0; + + if ((m_nBytesSent = WRITEV(m_socket, sendVector, nNumItems)) == CSimpleSocket::SocketError) + { + TranslateSocketError(); + } + + return m_nBytesSent; +} + + +//------------------------------------------------------------------------------ +// +// SetReceiveTimeout() +// +//------------------------------------------------------------------------------ +bool CSimpleSocket::SetReceiveTimeout(int32 nRecvTimeoutSec, int32 nRecvTimeoutUsec) +{ + bool bRetVal = true; + + memset(&m_stRecvTimeout, 0, sizeof(struct timeval)); + + m_stRecvTimeout.tv_sec = nRecvTimeoutSec; + m_stRecvTimeout.tv_usec = nRecvTimeoutUsec; + + //-------------------------------------------------------------------------- + // Sanity check to make sure the options are supported! + //-------------------------------------------------------------------------- + if (SETSOCKOPT(m_socket, SOL_SOCKET, SO_RCVTIMEO, &m_stRecvTimeout, + sizeof(struct timeval)) == CSimpleSocket::SocketError) + { + bRetVal = false; + TranslateSocketError(); + } + + return bRetVal; +} + + +//------------------------------------------------------------------------------ +// +// SetSendTimeout() +// +//------------------------------------------------------------------------------ +bool CSimpleSocket::SetSendTimeout(int32 nSendTimeoutSec, int32 nSendTimeoutUsec) +{ + bool bRetVal = true; + + memset(&m_stSendTimeout, 0, sizeof(struct timeval)); + m_stSendTimeout.tv_sec = nSendTimeoutSec; + m_stSendTimeout.tv_usec = nSendTimeoutUsec; + + //-------------------------------------------------------------------------- + // Sanity check to make sure the options are supported! + //-------------------------------------------------------------------------- + if (SETSOCKOPT(m_socket, SOL_SOCKET, SO_SNDTIMEO, &m_stSendTimeout, + sizeof(struct timeval)) == CSimpleSocket::SocketError) + { + bRetVal = false; + TranslateSocketError(); + } + + return bRetVal; +} + + +//------------------------------------------------------------------------------ +// +// SetOptionReuseAddr() +// +//------------------------------------------------------------------------------ +bool CSimpleSocket::SetOptionReuseAddr() +{ + bool bRetVal = false; + int32 nReuse = IPTOS_LOWDELAY; + + if (SETSOCKOPT(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&nReuse, sizeof(int32)) == 0) + { + bRetVal = true; + } + + TranslateSocketError(); + + return bRetVal; +} + + +//------------------------------------------------------------------------------ +// +// SetOptionLinger() +// +//------------------------------------------------------------------------------ +bool CSimpleSocket::SetOptionLinger(bool bEnable, uint16 nTime) +{ + bool bRetVal = false; + + m_stLinger.l_onoff = (bEnable == true) ? 1: 0; + m_stLinger.l_linger = nTime; + + if (SETSOCKOPT(m_socket, SOL_SOCKET, SO_LINGER, &m_stLinger, sizeof(m_stLinger)) == 0) + { + bRetVal = true; + } + + TranslateSocketError(); + + return bRetVal; +} + + +//------------------------------------------------------------------------------ +// +// Receive() - Attempts to receive a block of data on an established +// connection. Data is received in an internal buffer managed +// by the class. This buffer is only valid until the next call +// to Receive(), a call to Close(), or until the object goes out +// of scope. +// +//------------------------------------------------------------------------------ +int32 CSimpleSocket::Receive(int32 nMaxBytes, uint8 * pBuffer ) +{ + m_nBytesReceived = 0; + + //-------------------------------------------------------------------------- + // If the socket is invalid then return false. + //-------------------------------------------------------------------------- + if (IsSocketValid() == false) + { + return m_nBytesReceived; + } + + uint8 * pWorkBuffer = pBuffer; + if ( pBuffer == NULL ) + { + //-------------------------------------------------------------------------- + // Free existing buffer and allocate a new buffer the size of + // nMaxBytes. + //-------------------------------------------------------------------------- + if ((m_pBuffer != NULL) && (nMaxBytes != m_nBufferSize)) + { + delete [] m_pBuffer; + m_pBuffer = NULL; + } + + //-------------------------------------------------------------------------- + // Allocate a new internal buffer to receive data. + //-------------------------------------------------------------------------- + if (m_pBuffer == NULL) + { + m_nBufferSize = nMaxBytes; + m_pBuffer = new uint8[nMaxBytes]; + } + + pWorkBuffer = m_pBuffer; + } + + SetSocketError(SocketSuccess); + + m_timer.Initialize(); + m_timer.SetStartTime(); + + switch (m_nSocketType) + { + //---------------------------------------------------------------------- + // If zero bytes are received, then return. If SocketERROR is + // received, free buffer and return CSocket::SocketError (-1) to caller. + //---------------------------------------------------------------------- + case CSimpleSocket::SocketTypeTcp: + { + do + { + m_nBytesReceived = RECV(m_socket, (pWorkBuffer + m_nBytesReceived), + nMaxBytes, m_nFlags); + TranslateSocketError(); + } while ((GetSocketError() == CSimpleSocket::SocketInterrupted)); + + break; + } + case CSimpleSocket::SocketTypeUdp: + { + uint32 srcSize; + + srcSize = sizeof(struct sockaddr_in); + + if (GetMulticast() == true) + { + do + { + m_nBytesReceived = RECVFROM(m_socket, pWorkBuffer, nMaxBytes, 0, + &m_stMulticastGroup, &srcSize); + TranslateSocketError(); + } while (GetSocketError() == CSimpleSocket::SocketInterrupted); + } + else + { + do + { + m_nBytesReceived = RECVFROM(m_socket, pWorkBuffer, nMaxBytes, 0, + &m_stClientSockaddr, &srcSize); + TranslateSocketError(); + } while (GetSocketError() == CSimpleSocket::SocketInterrupted); + } + + break; + } + default: + break; + } + + m_timer.SetEndTime(); + TranslateSocketError(); + + //-------------------------------------------------------------------------- + // If we encounter an error translate the error code and return. One + // possible error code could be EAGAIN (EWOULDBLOCK) if the socket is + // non-blocking. This does not mean there is an error, but no data is + // yet available on the socket. + //-------------------------------------------------------------------------- + if (m_nBytesReceived == CSimpleSocket::SocketError) + { + if (m_pBuffer != NULL) + { + delete [] m_pBuffer; + m_pBuffer = NULL; + } + } + + return m_nBytesReceived; +} + + +//------------------------------------------------------------------------------ +// +// SetNonblocking() +// +//------------------------------------------------------------------------------ +bool CSimpleSocket::SetNonblocking(void) +{ + int32 nCurFlags; + +#if WIN32 + nCurFlags = 1; + + if (ioctlsocket(m_socket, FIONBIO, (ULONG *)&nCurFlags) != 0) + { + TranslateSocketError(); + return false; + } +#else + if ((nCurFlags = fcntl(m_socket, F_GETFL)) < 0) + { + TranslateSocketError(); + return false; + } + + nCurFlags |= O_NONBLOCK; + + if (fcntl(m_socket, F_SETFL, nCurFlags) != 0) + { + TranslateSocketError(); + return false; + } +#endif + + m_bIsBlocking = false; + + return true; +} + + +//------------------------------------------------------------------------------ +// +// SetBlocking() +// +//------------------------------------------------------------------------------ +bool CSimpleSocket::SetBlocking(void) +{ + int32 nCurFlags; + +#if WIN32 + nCurFlags = 0; + + if (ioctlsocket(m_socket, FIONBIO, (ULONG *)&nCurFlags) != 0) + { + return false; + } +#else + if ((nCurFlags = fcntl(m_socket, F_GETFL)) < 0) + { + TranslateSocketError(); + return false; + } + + nCurFlags &= (~O_NONBLOCK); + + if (fcntl(m_socket, F_SETFL, nCurFlags) != 0) + { + TranslateSocketError(); + return false; + } +#endif + m_bIsBlocking = true; + + return true; +} + + +//------------------------------------------------------------------------------ +// +// SendFile() - stands-in for system provided sendfile +// +//------------------------------------------------------------------------------ +int32 CSimpleSocket::SendFile(int32 nOutFd, int32 nInFd, off_t *pOffset, int32 nCount) +{ + int32 nOutCount = CSimpleSocket::SocketError; + + static char szData[SOCKET_SENDFILE_BLOCKSIZE]; + int32 nInCount = 0; + + if (lseek(nInFd, *pOffset, SEEK_SET) == -1) + { + return -1; + } + + while (nOutCount < nCount) + { + nInCount = (nCount - nOutCount) < SOCKET_SENDFILE_BLOCKSIZE ? (nCount - nOutCount) : SOCKET_SENDFILE_BLOCKSIZE; + + if ((read(nInFd, szData, nInCount)) != (int32)nInCount) + { + return -1; + } + + if ((SEND(nOutFd, szData, nInCount, 0)) != (int32)nInCount) + { + return -1; + } + + nOutCount += nInCount; + } + + *pOffset += nOutCount; + + TranslateSocketError(); + + return nOutCount; +} + + +//------------------------------------------------------------------------------ +// +// TranslateSocketError() - +// +//------------------------------------------------------------------------------ +void CSimpleSocket::TranslateSocketError(void) +{ +#if defined(_LINUX) || defined(_DARWIN) + switch (errno) + { + case EXIT_SUCCESS: + SetSocketError(CSimpleSocket::SocketSuccess); + break; + case ENOTCONN: + SetSocketError(CSimpleSocket::SocketNotconnected); + break; + case ENOTSOCK: + case EBADF: + case EACCES: + case EAFNOSUPPORT: + case EMFILE: + case ENFILE: + case ENOBUFS: + case ENOMEM: + case EPROTONOSUPPORT: + case EPIPE: + SetSocketError(CSimpleSocket::SocketInvalidSocket); + break; + case ECONNREFUSED : + SetSocketError(CSimpleSocket::SocketConnectionRefused); + break; + case ETIMEDOUT: + SetSocketError(CSimpleSocket::SocketTimedout); + break; + case EINPROGRESS: + SetSocketError(CSimpleSocket::SocketEinprogress); + break; + case EWOULDBLOCK: + // case EAGAIN: + SetSocketError(CSimpleSocket::SocketEwouldblock); + break; + case EINTR: + SetSocketError(CSimpleSocket::SocketInterrupted); + break; + case ECONNABORTED: + SetSocketError(CSimpleSocket::SocketConnectionAborted); + break; + case EINVAL: + case EPROTO: + SetSocketError(CSimpleSocket::SocketProtocolError); + break; + case EPERM: + SetSocketError(CSimpleSocket::SocketFirewallError); + break; + case EFAULT: + SetSocketError(CSimpleSocket::SocketInvalidSocketBuffer); + break; + case ECONNRESET: + case ENOPROTOOPT: + SetSocketError(CSimpleSocket::SocketConnectionReset); + break; + default: + SetSocketError(CSimpleSocket::SocketEunknown); + break; + } +#endif +#ifdef WIN32 + int32 nError = WSAGetLastError(); + switch (nError) + { + case EXIT_SUCCESS: + SetSocketError(CSimpleSocket::SocketSuccess); + break; + case WSAEBADF: + case WSAENOTCONN: + SetSocketError(CSimpleSocket::SocketNotconnected); + break; + case WSAEINTR: + SetSocketError(CSimpleSocket::SocketInterrupted); + break; + case WSAEACCES: + case WSAEAFNOSUPPORT: + case WSAEINVAL: + case WSAEMFILE: + case WSAENOBUFS: + case WSAEPROTONOSUPPORT: + SetSocketError(CSimpleSocket::SocketInvalidSocket); + break; + case WSAECONNREFUSED : + SetSocketError(CSimpleSocket::SocketConnectionRefused); + break; + case WSAETIMEDOUT: + SetSocketError(CSimpleSocket::SocketTimedout); + break; + case WSAEINPROGRESS: + SetSocketError(CSimpleSocket::SocketEinprogress); + break; + case WSAECONNABORTED: + SetSocketError(CSimpleSocket::SocketConnectionAborted); + break; + case WSAEWOULDBLOCK: + SetSocketError(CSimpleSocket::SocketEwouldblock); + break; + case WSAENOTSOCK: + SetSocketError(CSimpleSocket::SocketInvalidSocket); + break; + case WSAECONNRESET: + SetSocketError(CSimpleSocket::SocketConnectionReset); + break; + case WSANO_DATA: + SetSocketError(CSimpleSocket::SocketInvalidAddress); + break; + case WSAEADDRINUSE: + SetSocketError(CSimpleSocket::SocketAddressInUse); + break; + case WSAEFAULT: + SetSocketError(CSimpleSocket::SocketInvalidPointer); + break; + default: + SetSocketError(CSimpleSocket::SocketEunknown); + break; + } +#endif +} + +//------------------------------------------------------------------------------ +// +// DescribeError() +// +//------------------------------------------------------------------------------ + +const char *CSimpleSocket::DescribeError(CSocketError err) +{ + switch (err) { + case CSimpleSocket::SocketError: + return "Generic socket error translates to error below."; + case CSimpleSocket::SocketSuccess: + return "No socket error."; + case CSimpleSocket::SocketInvalidSocket: + return "Invalid socket handle."; + case CSimpleSocket::SocketInvalidAddress: + return "Invalid destination address specified."; + case CSimpleSocket::SocketInvalidPort: + return "Invalid destination port specified."; + case CSimpleSocket::SocketConnectionRefused: + return "No server is listening at remote address."; + case CSimpleSocket::SocketTimedout: + return "Timed out while attempting operation."; + case CSimpleSocket::SocketEwouldblock: + return "Operation would block if socket were blocking."; + case CSimpleSocket::SocketNotconnected: + return "Currently not connected."; + case CSimpleSocket::SocketEinprogress: + return "Socket is non-blocking and the connection cannot be completed immediately"; + case CSimpleSocket::SocketInterrupted: + return "Call was interrupted by a signal that was caught before a valid connection arrived."; + case CSimpleSocket::SocketConnectionAborted: + return "The connection has been aborted."; + case CSimpleSocket::SocketProtocolError: + return "Invalid protocol for operation."; + case CSimpleSocket::SocketFirewallError: + return "Firewall rules forbid connection."; + case CSimpleSocket::SocketInvalidSocketBuffer: + return "The receive buffer point outside the process's address space."; + case CSimpleSocket::SocketConnectionReset: + return "Connection was forcibly closed by the remote host."; + case CSimpleSocket::SocketAddressInUse: + return "Address already in use."; + case CSimpleSocket::SocketInvalidPointer: + return "Pointer type supplied as argument is invalid."; + case CSimpleSocket::SocketEunknown: + return "Unknown error"; + default: + return "No such CSimpleSocket error"; + } +} + +//------------------------------------------------------------------------------ +// +// Select() +// +//------------------------------------------------------------------------------ +bool CSimpleSocket::Select(int32 nTimeoutSec, int32 nTimeoutUSec) +{ + bool bRetVal = false; + struct timeval *pTimeout = NULL; + struct timeval timeout; + int32 nNumDescriptors = -1; + int32 nError = 0; + + FD_ZERO(&m_errorFds); + FD_ZERO(&m_readFds); + FD_ZERO(&m_writeFds); + FD_SET(m_socket, &m_errorFds); + FD_SET(m_socket, &m_readFds); + FD_SET(m_socket, &m_writeFds); + + //--------------------------------------------------------------------- + // If timeout has been specified then set value, otherwise set timeout + // to NULL which will block until a descriptor is ready for read/write + // or an error has occurred. + //--------------------------------------------------------------------- + if ((nTimeoutSec > 0) || (nTimeoutUSec > 0)) + { + timeout.tv_sec = nTimeoutSec; + timeout.tv_usec = nTimeoutUSec; + pTimeout = &timeout; + } + + nNumDescriptors = SELECT(m_socket+1, &m_readFds, &m_writeFds, &m_errorFds, pTimeout); +// nNumDescriptors = SELECT(m_socket+1, &m_readFds, NULL, NULL, pTimeout); + + //---------------------------------------------------------------------- + // Handle timeout + //---------------------------------------------------------------------- + if (nNumDescriptors == 0) + { + SetSocketError(CSimpleSocket::SocketTimedout); + } + //---------------------------------------------------------------------- + // If a file descriptor (read/write) is set then check the + // socket error (SO_ERROR) to see if there is a pending error. + //---------------------------------------------------------------------- + else if ((FD_ISSET(m_socket, &m_readFds)) || (FD_ISSET(m_socket, &m_writeFds))) + { + int32 nLen = sizeof(nError); + + if (GETSOCKOPT(m_socket, SOL_SOCKET, SO_ERROR, &nError, &nLen) == 0) + { + errno = nError; + + if (nError == 0) + { + bRetVal = true; + } + } + + TranslateSocketError(); + } + + return bRetVal; +} + diff --git a/examples/ThirdPartyLibs/clsocket/src/SimpleSocket.h b/examples/ThirdPartyLibs/clsocket/src/SimpleSocket.h new file mode 100644 index 000000000..603f46715 --- /dev/null +++ b/examples/ThirdPartyLibs/clsocket/src/SimpleSocket.h @@ -0,0 +1,583 @@ +/*---------------------------------------------------------------------------*/ +/* */ +/* SimpleSocket.h - Simple Socket base class decleration. */ +/* */ +/* Author : Mark Carrier (mark@carrierlabs.com) */ +/* */ +/*---------------------------------------------------------------------------*/ +/* Copyright (c) 2007-2009 CarrierLabs, LLC. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. The name "CarrierLabs" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * mark@carrierlabs.com. + * + * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + *----------------------------------------------------------------------------*/ +#ifndef __SOCKET_H__ +#define __SOCKET_H__ + +#include +#include +#include +#include +#include + +#if defined(_LINUX) || defined (_DARWIN) +#include +#include +#include +#include +#include +#include +#endif +#ifdef _LINUX +#include +#include +#include +#include +#endif +#ifdef _DARWIN +#include +#endif +#if defined(_LINUX) || defined (_DARWIN) +#include +#include +#include +#include +#endif + +#ifdef _WIN32 +#include +#include +#include + +#define IPTOS_LOWDELAY 0x10 + +#endif +#include "Host.h" +#include "StatTimer.h" + +//----------------------------------------------------------------------------- +// General class macro definitions and typedefs +//----------------------------------------------------------------------------- +#ifndef INVALID_SOCKET +#define INVALID_SOCKET ~(0) +#endif + +#define SOCKET_SENDFILE_BLOCKSIZE 8192 + +/// Provides a platform independent class to for socket development. +/// This class is designed to abstract socket communication development in a +/// platform independent manner. +/// - Socket types +/// -# CActiveSocket Class +/// -# CPassiveSocket Class +class CSimpleSocket { +public: + /// Defines the three possible states for shuting down a socket. + typedef enum + { + Receives = SHUT_RD, ///< Shutdown passive socket. + Sends = SHUT_WR, ///< Shutdown active socket. + Both = SHUT_RDWR ///< Shutdown both active and passive sockets. + } CShutdownMode; + + /// Defines the socket types defined by CSimpleSocket class. + typedef enum + { + SocketTypeInvalid, ///< Invalid socket type. + SocketTypeTcp, ///< Defines socket as TCP socket. + SocketTypeUdp, ///< Defines socket as UDP socket. + SocketTypeTcp6, ///< Defines socket as IPv6 TCP socket. + SocketTypeUdp6, ///< Defines socket as IPv6 UDP socket. + SocketTypeRaw ///< Provides raw network protocol access. + } CSocketType; + + /// Defines all error codes handled by the CSimpleSocket class. + typedef enum + { + SocketError = -1, ///< Generic socket error translates to error below. + SocketSuccess = 0, ///< No socket error. + SocketInvalidSocket, ///< Invalid socket handle. + SocketInvalidAddress, ///< Invalid destination address specified. + SocketInvalidPort, ///< Invalid destination port specified. + SocketConnectionRefused, ///< No server is listening at remote address. + SocketTimedout, ///< Timed out while attempting operation. + SocketEwouldblock, ///< Operation would block if socket were blocking. + SocketNotconnected, ///< Currently not connected. + SocketEinprogress, ///< Socket is non-blocking and the connection cannot be completed immediately + SocketInterrupted, ///< Call was interrupted by a signal that was caught before a valid connection arrived. + SocketConnectionAborted, ///< The connection has been aborted. + SocketProtocolError, ///< Invalid protocol for operation. + SocketFirewallError, ///< Firewall rules forbid connection. + SocketInvalidSocketBuffer, ///< The receive buffer point outside the process's address space. + SocketConnectionReset, ///< Connection was forcibly closed by the remote host. + SocketAddressInUse, ///< Address already in use. + SocketInvalidPointer, ///< Pointer type supplied as argument is invalid. + SocketEunknown ///< Unknown error please report to mark@carrierlabs.com + } CSocketError; + +public: + CSimpleSocket(CSocketType type = SocketTypeTcp); + CSimpleSocket(CSimpleSocket &socket); + + virtual ~CSimpleSocket() + { + if (m_pBuffer != NULL) + { + delete [] m_pBuffer; + m_pBuffer = NULL; + } + }; + + /// Initialize instance of CSocket. This method MUST be called before an + /// object can be used. Errors : CSocket::SocketProtocolError, + /// CSocket::SocketInvalidSocket, + /// @return true if properly initialized. + virtual bool Initialize(void); + + /// Close socket + /// @return true if successfully closed otherwise returns false. + virtual bool Close(void); + + /// Shutdown shut down socket send and receive operations + /// CShutdownMode::Receives - Disables further receive operations. + /// CShutdownMode::Sends - Disables further send operations. + /// CShutdownBoth:: - Disables further send and receive operations. + /// @param nShutdown specifies the type of shutdown. + /// @return true if successfully shutdown otherwise returns false. + virtual bool Shutdown(CShutdownMode nShutdown); + + /// Examine the socket descriptor sets currently owned by the instance of + /// the socket class (the readfds, writefds, and errorfds parameters) to + /// see whether some of their descriptors are ready for reading, are ready + /// for writing, or have an exceptional condition pending, respectively. + /// Block until an event happens on the specified file descriptors. + /// @return true if socket has data ready, or false if not ready or timed out. + virtual bool Select(void) { + return Select(0,0); + }; + + /// Examine the socket descriptor sets currently owned by the instance of + /// the socket class (the readfds, writefds, and errorfds parameters) to + /// see whether some of their descriptors are ready for reading, are ready + /// for writing, or have an exceptional condition pending, respectively. + /// @param nTimeoutSec timeout in seconds for select. + /// @param nTimeoutUSec timeout in micro seconds for select. + /// @return true if socket has data ready, or false if not ready or timed out. + virtual bool Select(int32 nTimeoutSec, int32 nTimeoutUSec); + + /// Does the current instance of the socket object contain a valid socket + /// descriptor. + /// @return true if the socket object contains a valid socket descriptor. + virtual bool IsSocketValid(void) { + return (m_socket != SocketError); + }; + + /// Provides a standard error code for cross platform development by + /// mapping the operating system error to an error defined by the CSocket + /// class. + void TranslateSocketError(void); + + /// Returns a human-readable description of the given error code + /// or the last error code of a socket + static const char *DescribeError(CSocketError err); + inline const char *DescribeError() { + return DescribeError(m_socketErrno); + }; + + /// Attempts to receive a block of data on an established connection. + /// @param nMaxBytes maximum number of bytes to receive. + /// @param pBuffer, memory where to receive the data, + /// NULL receives to internal buffer returned with GetData() + /// Non-NULL receives directly there, but GetData() will return WRONG ptr! + /// @return number of bytes actually received. + /// @return of zero means the connection has been shutdown on the other side. + /// @return of -1 means that an error has occurred. + virtual int32 Receive(int32 nMaxBytes = 1, uint8 * pBuffer = 0); + + /// Attempts to send a block of data on an established connection. + /// @param pBuf block of data to be sent. + /// @param bytesToSend size of data block to be sent. + /// @return number of bytes actually sent. + /// @return of zero means the connection has been shutdown on the other side. + /// @return of -1 means that an error has occurred. + virtual int32 Send(const uint8 *pBuf, size_t bytesToSend); + + /// Attempts to send at most nNumItem blocks described by sendVector + /// to the socket descriptor associated with the socket object. + /// @param sendVector pointer to an array of iovec structures + /// @param nNumItems number of items in the vector to process + ///
\b NOTE: Buffers are processed in the order specified. + /// @return number of bytes actually sent, return of zero means the + /// connection has been shutdown on the other side, and a return of -1 + /// means that an error has occurred. + virtual int32 Send(const struct iovec *sendVector, int32 nNumItems); + + /// Copies data between one file descriptor and another. + /// On some systems this copying is done within the kernel, and thus is + /// more efficient than the combination of CSimpleSocket::Send and + /// CSimpleSocket::Receive, which would require transferring data to and + /// from user space. + ///
\b Note: This is available on all implementations, but the kernel + /// implementation is only available on Unix type systems. + /// @param nOutFd descriptor opened for writing. + /// @param nInFd descriptor opened for reading. + /// @param pOffset from which to start reading data from input file. + /// @param nCount number of bytes to copy between file descriptors. + /// @return number of bytes written to the out socket descriptor. + virtual int32 SendFile(int32 nOutFd, int32 nInFd, off_t *pOffset, int32 nCount); + + /// Returns blocking/non-blocking state of socket. + /// @return true if the socket is non-blocking, else return false. + bool IsNonblocking(void) { + return (m_bIsBlocking == false); + }; + + /// Set the socket to blocking. + /// @return true if successful set to blocking, else return false; + bool SetBlocking(void); + + /// Set the socket as non-blocking. + /// @return true if successful set to non-blocking, else return false; + bool SetNonblocking(void); + + /// Get a pointer to internal receive buffer. The user MUST not free this + /// pointer when finished. This memory is managed internally by the CSocket + /// class. + /// @return pointer to data if valid, else returns NULL. + uint8 *GetData(void) { + return m_pBuffer; + }; + + /// Returns the number of bytes received on the last call to + /// CSocket::Receive(). + /// @return number of bytes received. + int32 GetBytesReceived(void) { + return m_nBytesReceived; + }; + + /// Returns the number of bytes sent on the last call to + /// CSocket::Send(). + /// @return number of bytes sent. + int32 GetBytesSent(void) { + return m_nBytesSent; + }; + + /// Controls the actions taken when CSimpleSocket::Close is executed on a + /// socket object that has unsent data. The default value for this option + /// is \b off. + /// - Following are the three possible scenarios. + /// -# \b bEnable is false, CSimpleSocket::Close returns immediately, but + /// any unset data is transmitted (after CSimpleSocket::Close returns) + /// -# \b bEnable is true and \b nTime is zero, CSimpleSocket::Close return + /// immediately and any unsent data is discarded. + /// -# \b bEnable is true and \b nTime is nonzero, CSimpleSocket::Close does + /// not return until all unsent data is transmitted (or the connection is + /// Closed by the remote system). + ///

+ /// @param bEnable true to enable option false to disable option. + /// @param nTime time in seconds to linger. + /// @return true if option successfully set + bool SetOptionLinger(bool bEnable, uint16 nTime); + + /// Tells the kernel that even if this port is busy (in the TIME_WAIT state), + /// go ahead and reuse it anyway. If it is busy, but with another state, + /// you will still get an address already in use error. + /// @return true if option successfully set + bool SetOptionReuseAddr(); + + /// Gets the timeout value that specifies the maximum number of seconds a + /// call to CSimpleSocket::Open waits until it completes. + /// @return the length of time in seconds + int32 GetConnectTimeoutSec(void) { + return m_stConnectTimeout.tv_sec; + }; + + /// Gets the timeout value that specifies the maximum number of microseconds + /// a call to CSimpleSocket::Open waits until it completes. + /// @return the length of time in microseconds + int32 GetConnectTimeoutUSec(void) { + return m_stConnectTimeout.tv_usec; + }; + + /// Sets the timeout value that specifies the maximum amount of time a call + /// to CSimpleSocket::Receive waits until it completes. Use the method + /// CSimpleSocket::SetReceiveTimeout to specify the number of seconds to wait. + /// If a call to CSimpleSocket::Receive has blocked for the specified length of + /// time without receiving additional data, it returns with a partial count + /// or CSimpleSocket::GetSocketError set to CSimpleSocket::SocketEwouldblock if no data + /// were received. + /// @param nConnectTimeoutSec of timeout in seconds. + /// @param nConnectTimeoutUsec of timeout in microseconds. + /// @return true if socket connection timeout was successfully set. + void SetConnectTimeout(int32 nConnectTimeoutSec, int32 nConnectTimeoutUsec = 0) + { + m_stConnectTimeout.tv_sec = nConnectTimeoutSec; + m_stConnectTimeout.tv_usec = nConnectTimeoutUsec; + }; + + /// Gets the timeout value that specifies the maximum number of seconds a + /// a call to CSimpleSocket::Receive waits until it completes. + /// @return the length of time in seconds + int32 GetReceiveTimeoutSec(void) { + return m_stRecvTimeout.tv_sec; + }; + + /// Gets the timeout value that specifies the maximum number of microseconds + /// a call to CSimpleSocket::Receive waits until it completes. + /// @return the length of time in microseconds + int32 GetReceiveTimeoutUSec(void) { + return m_stRecvTimeout.tv_usec; + }; + + /// Sets the timeout value that specifies the maximum amount of time a call + /// to CSimpleSocket::Receive waits until it completes. Use the method + /// CSimpleSocket::SetReceiveTimeout to specify the number of seconds to wait. + /// If a call to CSimpleSocket::Receive has blocked for the specified length of + /// time without receiving additional data, it returns with a partial count + /// or CSimpleSocket::GetSocketError set to CSimpleSocket::SocketEwouldblock if no data + /// were received. + /// @param nRecvTimeoutSec of timeout in seconds. + /// @param nRecvTimeoutUsec of timeout in microseconds. + /// @return true if socket timeout was successfully set. + bool SetReceiveTimeout(int32 nRecvTimeoutSec, int32 nRecvTimeoutUsec = 0); + + /// Enable/disable multicast for a socket. This options is only valid for + /// socket descriptors of type CSimpleSocket::SocketTypeUdp. + /// @return true if multicast was enabled or false if socket type is not + /// CSimpleSocket::SocketTypeUdp and the error will be set to + /// CSimpleSocket::SocketProtocolError + bool SetMulticast(bool bEnable, uint8 multicastTTL = 1); + + /// Return true if socket is multicast or false is socket is unicast + /// @return true if multicast is enabled + bool GetMulticast() { + return m_bIsMulticast; + }; + + /// Bind socket to a specific interface when using multicast. + /// @return true if successfully bound to interface + bool BindInterface(const char *pInterface); + + /// Gets the timeout value that specifies the maximum number of seconds a + /// a call to CSimpleSocket::Send waits until it completes. + /// @return the length of time in seconds + int32 GetSendTimeoutSec(void) { + return m_stSendTimeout.tv_sec; + }; + + /// Gets the timeout value that specifies the maximum number of microseconds + /// a call to CSimpleSocket::Send waits until it completes. + /// @return the length of time in microseconds + int32 GetSendTimeoutUSec(void) { + return m_stSendTimeout.tv_usec; + }; + + /// Gets the timeout value that specifies the maximum amount of time a call + /// to CSimpleSocket::Send waits until it completes. + /// @return the length of time in seconds + bool SetSendTimeout(int32 nSendTimeoutSec, int32 nSendTimeoutUsec = 0); + + /// Returns the last error that occured for the instace of the CSimpleSocket + /// instance. This method should be called immediately to retrieve the + /// error code for the failing mehtod call. + /// @return last error that occured. + CSocketError GetSocketError(void) { + return m_socketErrno; + }; + + /// Get the total time the of the last operation in milliseconds. + /// @return number of milliseconds of last operation. + uint32 GetTotalTimeMs() { + return m_timer.GetMilliSeconds(); + }; + + /// Get the total time the of the last operation in microseconds. + /// @return number of microseconds or last operation. + uint32 GetTotalTimeUsec() { + return m_timer.GetMicroSeconds(); + }; + + /// Return Differentiated Services Code Point (DSCP) value currently set on the socket object. + /// @return DSCP for current socket object. + ///

\b NOTE: Windows special notes http://support.microsoft.com/kb/248611. + int GetSocketDscp(void); + + /// Set Differentiated Services Code Point (DSCP) for socket object. + /// @param nDscp value of TOS setting which will be converted to DSCP + /// @return true if DSCP value was properly set + ///

\b NOTE: Windows special notes http://support.microsoft.com/kb/248611. + bool SetSocketDscp(int nDscp); + + /// Return socket descriptor + /// @return socket descriptor which is a signed 32 bit integer. + SOCKET GetSocketDescriptor() { + return m_socket; + }; + + /// Return socket descriptor + /// @return socket descriptor which is a signed 32 bit integer. + CSocketType GetSocketType() { + return m_nSocketType; + }; + + /// Returns clients Internet host address as a string in standard numbers-and-dots notation. + /// @return NULL if invalid + const char *GetClientAddr() { + return inet_ntoa(m_stClientSockaddr.sin_addr); + }; + + /// Returns the port number on which the client is connected. + /// @return client port number. + uint16 GetClientPort() { + return m_stClientSockaddr.sin_port; + }; + + /// Returns server Internet host address as a string in standard numbers-and-dots notation. + /// @return NULL if invalid + const char *GetServerAddr() { + return inet_ntoa(m_stServerSockaddr.sin_addr); + }; + + /// Returns the port number on which the server is connected. + /// @return server port number. + uint16 GetServerPort() { + return ntohs(m_stServerSockaddr.sin_port); + }; + + /// Get the TCP receive buffer window size for the current socket object. + ///

\b NOTE: Linux will set the receive buffer to twice the value passed. + /// @return zero on failure else the number of bytes of the TCP receive buffer window size if successful. + uint32 GetReceiveWindowSize() { + return GetWindowSize(SO_RCVBUF); + }; + + /// Get the TCP send buffer window size for the current socket object. + ///

\b NOTE: Linux will set the send buffer to twice the value passed. + /// @return zero on failure else the number of bytes of the TCP receive buffer window size if successful. + uint32 GetSendWindowSize() { + return GetWindowSize(SO_SNDBUF); + }; + + /// Set the TCP receive buffer window size for the current socket object. + ///

\b NOTE: Linux will set the receive buffer to twice the value passed. + /// @return zero on failure else the number of bytes of the TCP send buffer window size if successful. + uint32 SetReceiveWindowSize(uint32 nWindowSize) { + return SetWindowSize(SO_RCVBUF, nWindowSize); + }; + + /// Set the TCP send buffer window size for the current socket object. + ///

\b NOTE: Linux will set the send buffer to twice the value passed. + /// @return zero on failure else the number of bytes of the TCP send buffer window size if successful. + uint32 SetSendWindowSize(uint32 nWindowSize) { + return SetWindowSize(SO_SNDBUF, nWindowSize); + }; + + /// Disable the Nagle algorithm (Set TCP_NODELAY to true) + /// @return false if failed to set socket option otherwise return true; + bool DisableNagleAlgoritm(); + + /// Enable the Nagle algorithm (Set TCP_NODELAY to false) + /// @return false if failed to set socket option otherwise return true; + bool EnableNagleAlgoritm(); + + +protected: + /// Set internal socket error to that specified error + /// @param error type of error + void SetSocketError(CSimpleSocket::CSocketError error) { + m_socketErrno = error; + }; + + /// Set object socket handle to that specified as parameter + /// @param socket value of socket descriptor + void SetSocketHandle(SOCKET socket) { + m_socket = socket; + }; + +private: + /// Generic function used to get the send/receive window size + /// @return zero on failure else the number of bytes of the TCP window size if successful. + uint32 GetWindowSize(uint32 nOptionName); + + /// Generic function used to set the send/receive window size + /// @return zero on failure else the number of bytes of the TCP window size if successful. + uint32 SetWindowSize(uint32 nOptionName, uint32 nWindowSize); + + + /// Attempts to send at most nNumItem blocks described by sendVector + /// to the socket descriptor associated with the socket object. + /// @param sendVector pointer to an array of iovec structures + /// @param nNumItems number of items in the vector to process + ///
\b Note: This implementation is for systems that don't natively + /// support this functionality. + /// @return number of bytes actually sent, return of zero means the + /// connection has been shutdown on the other side, and a return of -1 + /// means that an error has occurred. + int32 Writev(const struct iovec *pVector, size_t nCount); + + /// Flush the socket descriptor owned by the object. + /// @return true data was successfully sent, else return false; + bool Flush(); + + CSimpleSocket *operator=(CSimpleSocket &socket); + +protected: + SOCKET m_socket; /// socket handle + CSocketError m_socketErrno; /// number of last error + uint8 *m_pBuffer; /// internal send/receive buffer + int32 m_nBufferSize; /// size of internal send/receive buffer + int32 m_nSocketDomain; /// socket type PF_INET, PF_INET6 + CSocketType m_nSocketType; /// socket type - UDP, TCP or RAW + int32 m_nBytesReceived; /// number of bytes received + int32 m_nBytesSent; /// number of bytes sent + uint32 m_nFlags; /// socket flags + bool m_bIsBlocking; /// is socket blocking + bool m_bIsMulticast; /// is the UDP socket multicast; + struct timeval m_stConnectTimeout; /// connection timeout + struct timeval m_stRecvTimeout; /// receive timeout + struct timeval m_stSendTimeout; /// send timeout + struct sockaddr_in m_stServerSockaddr; /// server address + struct sockaddr_in m_stClientSockaddr; /// client address + struct sockaddr_in m_stMulticastGroup; /// multicast group to bind to + struct linger m_stLinger; /// linger flag + CStatTimer m_timer; /// internal statistics. +#ifdef WIN32 + WSADATA m_hWSAData; /// Windows +#endif + fd_set m_writeFds; /// write file descriptor set + fd_set m_readFds; /// read file descriptor set + fd_set m_errorFds; /// error file descriptor set +}; + + +#endif /* __SOCKET_H__ */ + diff --git a/examples/ThirdPartyLibs/clsocket/src/StatTimer.h b/examples/ThirdPartyLibs/clsocket/src/StatTimer.h new file mode 100644 index 000000000..2110add9f --- /dev/null +++ b/examples/ThirdPartyLibs/clsocket/src/StatTimer.h @@ -0,0 +1,114 @@ +/*----------------------------------------------------------------------------*/ +/* */ +/* StatTimer.h: interface for the CStatTimer class. */ +/* */ +/* Author: Mark Carrier (mark@carrierlabs.com) */ +/* */ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2006 CarrierLabs, LLC. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. The name "CarrierLabs" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * mark@carrierlabs.com. + * + * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + *----------------------------------------------------------------------------*/ +#ifndef __CSTATTIMER_H__ +#define __CSTATTIMER_H__ + +#include + +#if WIN32 + #include + #include +#endif + +#ifdef _LINUX + #include + #include +#endif + +#include "Host.h" + +#if defined(WIN32) + #define GET_CLOCK_COUNT(x) QueryPerformanceCounter((LARGE_INTEGER *)x) +#else + #define GET_CLOCK_COUNT(x) gettimeofday(x, NULL) +#endif + +#define MILLISECONDS_CONVERSION 1000 +#define MICROSECONDS_CONVERSION 1000000 + +/// Class to abstract socket communications in a cross platform manner. +/// This class is designed +class CStatTimer { +public: + CStatTimer() + { + }; + + ~CStatTimer() + { + }; + + void Initialize() + { + memset(&m_startTime, 0, sizeof(struct timeval)); + memset(&m_endTime, 0, sizeof(struct timeval)); + }; + + struct timeval GetStartTime() { return m_startTime; }; + void SetStartTime() { GET_CLOCK_COUNT(&m_startTime); }; + + struct timeval GetEndTime() { return m_endTime; }; + void SetEndTime() { GET_CLOCK_COUNT(&m_endTime); }; + + uint32 GetMilliSeconds() { return (CalcTotalUSec() / MILLISECONDS_CONVERSION); }; + uint32 GetMicroSeconds() { return (CalcTotalUSec()); }; + uint32 GetSeconds() { return (CalcTotalUSec() / MICROSECONDS_CONVERSION); }; + + uint32 GetCurrentTime() + { + struct timeval tmpTime; + GET_CLOCK_COUNT(&tmpTime); + return ((tmpTime.tv_sec * MICROSECONDS_CONVERSION) + tmpTime.tv_usec); + }; + +private: + uint32 CalcTotalUSec() { return (((m_endTime.tv_sec - m_startTime.tv_sec) * MICROSECONDS_CONVERSION) + + (m_endTime.tv_usec - m_startTime.tv_usec)); }; + + +private: + struct timeval m_startTime; + struct timeval m_endTime; +}; + +#endif // __CSTATTIMER_H__ diff --git a/test/clsocket/EchoServer.cpp b/test/clsocket/EchoServer.cpp new file mode 100644 index 000000000..4a27d278f --- /dev/null +++ b/test/clsocket/EchoServer.cpp @@ -0,0 +1,44 @@ + +#include "PassiveSocket.h" // Include header for active socket object definition + +#define MAX_PACKET 4096 + +int main(int argc, char **argv) +{ + CPassiveSocket socket; + CActiveSocket *pClient = NULL; + + //-------------------------------------------------------------------------- + // Initialize our socket object + //-------------------------------------------------------------------------- + socket.Initialize(); + + socket.Listen("127.0.0.1", 6789); + + while (true) + { + if ((pClient = socket.Accept()) != NULL) + { + //---------------------------------------------------------------------- + // Receive request from the client. + //---------------------------------------------------------------------- + if (pClient->Receive(MAX_PACKET)) + { + //------------------------------------------------------------------ + // Send response to client and close connection to the client. + //------------------------------------------------------------------ + pClient->Send( pClient->GetData(), pClient->GetBytesReceived() ); + pClient->Close(); + } + + delete pClient; + } + } + + //----------------------------------------------------------------------------- + // Receive request from the client. + //----------------------------------------------------------------------------- + socket.Close(); + + return 1; +} diff --git a/test/clsocket/QueryDayTime.cpp b/test/clsocket/QueryDayTime.cpp new file mode 100644 index 000000000..a853abfab --- /dev/null +++ b/test/clsocket/QueryDayTime.cpp @@ -0,0 +1,49 @@ + +#include +#include "ActiveSocket.h" // Include header for active socket object definition + +int main(int argc, char **argv) +{ + CActiveSocket socket; // Instantiate active socket object (defaults to TCP). + char time[50]; + + memset(&time, 0, 50); + + //-------------------------------------------------------------------------- + // Initialize our socket object + //-------------------------------------------------------------------------- + socket.Initialize(); + + //-------------------------------------------------------------------------- + // Create a connection to the time server so that data can be sent + // and received. + //-------------------------------------------------------------------------- +// if (socket.Open("time-C.timefreq.bldrdoc.gov", 13)) + if (socket.Open("127.0.0.1", 6789)) + { + //---------------------------------------------------------------------- + // Send a requtest the server requesting the current time. + //---------------------------------------------------------------------- + const char* data = "Hello!"; + int len = strlen(data); + + if (socket.Send((const uint8 *)"HELLO\n", len)) + { + //---------------------------------------------------------------------- + // Receive response from the server. + //---------------------------------------------------------------------- + socket.Receive(len); + uint8* data = socket.GetData(); + memcpy(&time, data, len); + printf("%s\n", time); + + //---------------------------------------------------------------------- + // Close the connection. + //---------------------------------------------------------------------- + socket.Close(); + } + } + + + return 1; +} diff --git a/test/clsocket/RecvAsync.cpp b/test/clsocket/RecvAsync.cpp new file mode 100644 index 000000000..d4e415fd0 --- /dev/null +++ b/test/clsocket/RecvAsync.cpp @@ -0,0 +1,101 @@ +#include +#include "PassiveSocket.h" + +#ifdef WIN32 +#include + + // usually defined with #include + static void sleep( unsigned int seconds ) + { + Sleep( seconds * 1000 ); + } +#endif + +#define MAX_PACKET 4096 +#define TEST_PACKET "Test Packet" + +struct thread_data +{ + const char *pszServerAddr; + short int nPort; + int nNumBytesToReceive; + int nTotalPayloadSize; +}; + + +void *CreateTCPEchoServer(void *param) +{ + CPassiveSocket socket; + CActiveSocket *pClient = NULL; + struct thread_data *pData = (struct thread_data *)param; + int nBytesReceived = 0; + + socket.Initialize(); + socket.Listen(pData->pszServerAddr, pData->nPort); + + if ((pClient = socket.Accept()) != NULL) + { + while (nBytesReceived != pData->nTotalPayloadSize) + { + if (nBytesReceived += pClient->Receive(pData->nNumBytesToReceive)) + { + pClient->Send((const uint8 *)pClient->GetData(), pClient->GetBytesReceived()); + } + } + + sleep(100); + + delete pClient; + } + + socket.Close(); + + return NULL; +} + +int main(int argc, char **argv) +{ + pthread_t threadId; + struct thread_data thData; + CActiveSocket client; + char result[1024]; + + thData.pszServerAddr = "127.0.0.1"; + thData.nPort = 6789; + thData.nNumBytesToReceive = 1; + thData.nTotalPayloadSize = (int)strlen(TEST_PACKET); + + pthread_create(&threadId, 0, CreateTCPEchoServer, &thData); + sleep(1); // allow a second for the thread to create and listen + + client.Initialize(); + client.SetNonblocking(); + + if (client.Open("127.0.0.1", 6789)) + { + if (client.Send((uint8 *)TEST_PACKET, strlen(TEST_PACKET))) + { + int numBytes = -1; + int bytesReceived = 0; + + client.Select(); + + while (bytesReceived != strlen(TEST_PACKET)) + { + numBytes = client.Receive(MAX_PACKET); + + if (numBytes > 0) + { + bytesReceived += numBytes; + memset(result, 0, 1024); + memcpy(result, client.GetData(), numBytes); + printf("received %d bytes: '%s'\n", numBytes, result); + } + else + { + printf("Received %d bytes\n", numBytes); + } + } + } + } +} From 4faa6613c9e6457e85e10b543eadfb05d046b6c9 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Sun, 19 Feb 2017 11:48:01 -0800 Subject: [PATCH 03/12] first draft of premake/cmake build files for clsocket (tiny cross-platform TCP socket library) --- build3/premake4.lua | 6 ++++ examples/CMakeLists.txt | 2 +- .../ThirdPartyLibs/clsocket/CMakeLists.txt | 35 ++++--------------- examples/ThirdPartyLibs/clsocket/premake4.lua | 24 +++++++++++++ 4 files changed, 38 insertions(+), 29 deletions(-) create mode 100644 examples/ThirdPartyLibs/clsocket/premake4.lua diff --git a/build3/premake4.lua b/build3/premake4.lua index 525996461..a5187efa7 100644 --- a/build3/premake4.lua +++ b/build3/premake4.lua @@ -251,6 +251,7 @@ end include "../examples/ExtendedTutorials" include "../examples/SharedMemory" include "../examples/ThirdPartyLibs/BussIK" + include "../examples/MultiThreading" if _OPTIONS["lua"] then @@ -270,6 +271,11 @@ end include "../examples/ThirdPartyLibs/midi" end + if not _OPTIONS["no_clsocket"] then + include "../examples/ThirdPartyLibs/clsocket" + defines {"BT_ENABLE_CLSOCKET"} + end + if not _OPTIONS["no-enet"] then include "../examples/ThirdPartyLibs/enet" include "../test/enet/nat_punchthrough/client" diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 486b31742..4c21d89d8 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,6 +1,6 @@ SUBDIRS( HelloWorld BasicDemo ) IF(BUILD_BULLET3) - SUBDIRS( ExampleBrowser SharedMemory ThirdPartyLibs/Gwen ThirdPartyLibs/BussIK OpenGLWindow ) + SUBDIRS( ExampleBrowser SharedMemory ThirdPartyLibs/Gwen ThirdPartyLibs/BussIK ThirdPartyLibs/clsocket OpenGLWindow ) ENDIF() IF(BUILD_PYBULLET) SUBDIRS(pybullet) diff --git a/examples/ThirdPartyLibs/clsocket/CMakeLists.txt b/examples/ThirdPartyLibs/clsocket/CMakeLists.txt index 5f85d0d8c..4bc3adfe7 100644 --- a/examples/ThirdPartyLibs/clsocket/CMakeLists.txt +++ b/examples/ThirdPartyLibs/clsocket/CMakeLists.txt @@ -1,10 +1,10 @@ -cmake_minimum_required(VERSION 2.8 FATAL_ERROR) -project(clsocket) +#cmake_minimum_required(VERSION 2.8 FATAL_ERROR) +#project(clsocket) # set up versioning. -set(BUILD_MAJOR "1") -set(BUILD_MINOR "4") -set(BUILD_VERSION "3") +#set(BUILD_MAJOR "1") +#set(BUILD_MINOR "4") +#set(BUILD_VERSION "3") include_directories(src) @@ -45,13 +45,14 @@ elseif(WIN32) # Special MINGW stuff here elseif(MSVC) # Special MSVC stuff here + add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS) else() # No idea what it is, but there's a good chance it's too weird. MESSAGE( FATAL_ERROR "Using unknown WIN32 compiler... NOT. Please add to build system." ) endif() endif() -OPTION(CLSOCKET_SHARED "Build clsocket lib as shared." ON) +OPTION(CLSOCKET_SHARED "Build clsocket lib as shared." OFF) OPTION(CLSOCKET_DEP_ONLY "Build for use inside other CMake projects as dependency." OFF) # make the lib @@ -78,25 +79,3 @@ else() endif() -OPTION(CLSOCKET_EXAMPLES "Build the examples" ON) - -ADD_EXECUTABLE(echoserver-example examples/EchoServer.cpp) -TARGET_LINK_LIBRARIES(echoserver-example clsocket) - -ADD_EXECUTABLE(querydaytime-example examples/QueryDayTime.cpp) -TARGET_LINK_LIBRARIES(querydaytime-example clsocket) - - -if(UNIX) - - if(CLSOCKET_EXAMPLES) - ADD_EXECUTABLE(clsocket-example examples/RecvAsync.cpp) - TARGET_LINK_LIBRARIES(clsocket-example clsocket pthread) - if(NOT CLSOCKET_DEP_ONLY) - install(TARGETS clsocket-example DESTINATION bin) - endif() - - - endif() -endif() - diff --git a/examples/ThirdPartyLibs/clsocket/premake4.lua b/examples/ThirdPartyLibs/clsocket/premake4.lua new file mode 100644 index 000000000..896185095 --- /dev/null +++ b/examples/ThirdPartyLibs/clsocket/premake4.lua @@ -0,0 +1,24 @@ + project "clsocket" + + kind "StaticLib" + + if os.is("Windows") then + defines { "WIN32","_WINSOCK_DEPRECATED_NO_WARNINGS" } + end + if os.is("Linux") then + defines {"HAS_SOCKLEN_T","_LINUX"} + end + if os.is("MacOSX") then + defines {"HAS_SOCKLEN_T","_DARWIN"} + end + + + includedirs { + ".","include" + } + files { + "src/SimpleSocket.cpp", + "src/ActiveSocket.cpp", + "src/PassiveSocket.cpp", + "**.h" + } From 3faab1b019c231f20c3d80e9c9c36cc7f3e88d63 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Sun, 19 Feb 2017 12:08:58 -0800 Subject: [PATCH 04/12] adjusted clsocket build and test, so there is an EchoServer and QueryDayTime sending a string to the EchoServer. --- build3/premake4.lua | 17 +++++-- examples/ThirdPartyLibs/clsocket/premake4.lua | 2 +- test/clsocket/EchoServer.cpp | 4 ++ test/clsocket/QueryDayTime.cpp | 8 +-- test/clsocket/premake4.lua | 51 +++++++++++++++++++ 5 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 test/clsocket/premake4.lua diff --git a/build3/premake4.lua b/build3/premake4.lua index a5187efa7..345091d3e 100644 --- a/build3/premake4.lua +++ b/build3/premake4.lua @@ -71,10 +71,17 @@ description = "Don't build Extras" } + newoption + { + trigger = "no-clsocket", + description = "Disable clsocket and clsocket tests (used for optional TCP networking in pybullet and shared memory C-API)" + } + + newoption { trigger = "no-enet", - description = "Disable enet and enet tests" + description = "Disable enet and enet tests (used for optional UDP networking in pybullet and shared memory C-API)" } newoption @@ -271,18 +278,20 @@ end include "../examples/ThirdPartyLibs/midi" end - if not _OPTIONS["no_clsocket"] then - include "../examples/ThirdPartyLibs/clsocket" + if not _OPTIONS["no-clsocket"] then defines {"BT_ENABLE_CLSOCKET"} + include "../examples/ThirdPartyLibs/clsocket" + include "../test/clsocket" end if not _OPTIONS["no-enet"] then + defines {"BT_ENABLE_ENET"} + include "../examples/ThirdPartyLibs/enet" include "../test/enet/nat_punchthrough/client" include "../test/enet/nat_punchthrough/server" include "../test/enet/chat/client" include "../test/enet/chat/server" - defines {"BT_ENABLE_ENET"} end if _OPTIONS["no-bullet3"] then diff --git a/examples/ThirdPartyLibs/clsocket/premake4.lua b/examples/ThirdPartyLibs/clsocket/premake4.lua index 896185095..57447b1fa 100644 --- a/examples/ThirdPartyLibs/clsocket/premake4.lua +++ b/examples/ThirdPartyLibs/clsocket/premake4.lua @@ -14,7 +14,7 @@ includedirs { - ".","include" + ".","include","src" } files { "src/SimpleSocket.cpp", diff --git a/test/clsocket/EchoServer.cpp b/test/clsocket/EchoServer.cpp index 4a27d278f..4173e5e6a 100644 --- a/test/clsocket/EchoServer.cpp +++ b/test/clsocket/EchoServer.cpp @@ -19,11 +19,15 @@ int main(int argc, char **argv) { if ((pClient = socket.Accept()) != NULL) { + int clientPort = socket.GetClientPort(); + printf("connected from %s:%d\n", socket.GetClientAddr(),clientPort); //---------------------------------------------------------------------- // Receive request from the client. //---------------------------------------------------------------------- if (pClient->Receive(MAX_PACKET)) { + char* msg = (char*) pClient->GetData(); + printf("received message [%s]\n",msg); //------------------------------------------------------------------ // Send response to client and close connection to the client. //------------------------------------------------------------------ diff --git a/test/clsocket/QueryDayTime.cpp b/test/clsocket/QueryDayTime.cpp index a853abfab..46084256d 100644 --- a/test/clsocket/QueryDayTime.cpp +++ b/test/clsocket/QueryDayTime.cpp @@ -24,10 +24,12 @@ int main(int argc, char **argv) //---------------------------------------------------------------------- // Send a requtest the server requesting the current time. //---------------------------------------------------------------------- - const char* data = "Hello!"; + char data[1024]; + sprintf(data,"%s","Hello!"); int len = strlen(data); - - if (socket.Send((const uint8 *)"HELLO\n", len)) + data[len]=0; + len++; + if (socket.Send((const uint8 *)data, len)) { //---------------------------------------------------------------------- // Receive response from the server. diff --git a/test/clsocket/premake4.lua b/test/clsocket/premake4.lua new file mode 100644 index 000000000..530cbdb90 --- /dev/null +++ b/test/clsocket/premake4.lua @@ -0,0 +1,51 @@ + + +project ("Test_clsocket_EchoServer") + + language "C++" + + kind "ConsoleApp" + + includedirs {"../../examples/ThirdPartyLibs/clsocket/src"} + + if os.is("Windows") then + defines { "WIN32" } + links {"Ws2_32","Winmm"} + end + if os.is("Linux") then + end + if os.is("MacOSX") then + end + + links {"clsocket"} + + files { + "EchoServer.cpp", + } + + + + +project ("Test_clsocket_QueryDayTime") + + language "C++" + + kind "ConsoleApp" + + includedirs {"../../examples/ThirdPartyLibs/clsocket/src"} + + if os.is("Windows") then + defines { "WIN32" } + links {"Ws2_32","Winmm"} + end + if os.is("Linux") then + end + if os.is("MacOSX") then + end + + links {"clsocket"} + + files { + "QueryDayTime.cpp", + } + From 970de9c4d77fac0fc9fdb4e9d2d8d4553aa6400d Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 20 Feb 2017 09:34:00 -0800 Subject: [PATCH 05/12] tcp echo/query test setup --- test/clsocket/EchoServer.cpp | 41 ++++++++++++++++++++++++---------- test/clsocket/QueryDayTime.cpp | 13 ++++++----- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/test/clsocket/EchoServer.cpp b/test/clsocket/EchoServer.cpp index 4173e5e6a..b5a3a0e21 100644 --- a/test/clsocket/EchoServer.cpp +++ b/test/clsocket/EchoServer.cpp @@ -13,7 +13,7 @@ int main(int argc, char **argv) //-------------------------------------------------------------------------- socket.Initialize(); - socket.Listen("127.0.0.1", 6789); + socket.Listen("localhost", 6667); while (true) { @@ -24,17 +24,34 @@ int main(int argc, char **argv) //---------------------------------------------------------------------- // Receive request from the client. //---------------------------------------------------------------------- - if (pClient->Receive(MAX_PACKET)) - { - char* msg = (char*) pClient->GetData(); - printf("received message [%s]\n",msg); - //------------------------------------------------------------------ - // Send response to client and close connection to the client. - //------------------------------------------------------------------ - pClient->Send( pClient->GetData(), pClient->GetBytesReceived() ); - pClient->Close(); - } - + while (1) + { + //printf("try receive\n"); + bool receivedData = false; + + if (pClient->Receive(MAX_PACKET)) + { + char* msg = (char*) pClient->GetData(); + //printf("received message [%s]\n",msg); + //------------------------------------------------------------------ + // Send response to client and close connection to the client. + //------------------------------------------------------------------ + pClient->Send( pClient->GetData(), pClient->GetBytesReceived() ); + receivedData = true; + if (strncmp(msg,"stop",4)==0) + { + printf("Stop request received\n"); + break; + } + } + if (!receivedData) + { + printf("Didn't receive data.\n"); + break; + } + } + printf("Disconnecting client.\n"); + pClient->Close(); delete pClient; } } diff --git a/test/clsocket/QueryDayTime.cpp b/test/clsocket/QueryDayTime.cpp index 46084256d..cb7381a64 100644 --- a/test/clsocket/QueryDayTime.cpp +++ b/test/clsocket/QueryDayTime.cpp @@ -19,7 +19,7 @@ int main(int argc, char **argv) // and received. //-------------------------------------------------------------------------- // if (socket.Open("time-C.timefreq.bldrdoc.gov", 13)) - if (socket.Open("127.0.0.1", 6789)) + if (socket.Open("localhost", 6667)) { //---------------------------------------------------------------------- // Send a requtest the server requesting the current time. @@ -34,10 +34,13 @@ int main(int argc, char **argv) //---------------------------------------------------------------------- // Receive response from the server. //---------------------------------------------------------------------- - socket.Receive(len); - uint8* data = socket.GetData(); - memcpy(&time, data, len); - printf("%s\n", time); + int rec = socket.Receive(len); + if (rec) + { + uint8* data = socket.GetData(); + memcpy(&time, data, len); + printf("%s\n", time); + } //---------------------------------------------------------------------- // Close the connection. From c10dfe6a80d000db38f4e66a8bddabc751550e18 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 20 Feb 2017 09:52:59 -0800 Subject: [PATCH 06/12] more tcp testing --- test/clsocket/EchoServer.cpp | 2 +- test/clsocket/QueryDayTime.cpp | 50 ++++++++++++++++++---------------- test/clsocket/premake4.lua | 13 ++++++--- 3 files changed, 37 insertions(+), 28 deletions(-) diff --git a/test/clsocket/EchoServer.cpp b/test/clsocket/EchoServer.cpp index b5a3a0e21..74c03ac7c 100644 --- a/test/clsocket/EchoServer.cpp +++ b/test/clsocket/EchoServer.cpp @@ -32,7 +32,7 @@ int main(int argc, char **argv) if (pClient->Receive(MAX_PACKET)) { char* msg = (char*) pClient->GetData(); - //printf("received message [%s]\n",msg); + printf("received message [%s]\n",msg); //------------------------------------------------------------------ // Send response to client and close connection to the client. //------------------------------------------------------------------ diff --git a/test/clsocket/QueryDayTime.cpp b/test/clsocket/QueryDayTime.cpp index cb7381a64..2211f37ce 100644 --- a/test/clsocket/QueryDayTime.cpp +++ b/test/clsocket/QueryDayTime.cpp @@ -19,35 +19,39 @@ int main(int argc, char **argv) // and received. //-------------------------------------------------------------------------- // if (socket.Open("time-C.timefreq.bldrdoc.gov", 13)) - if (socket.Open("localhost", 6667)) - { - //---------------------------------------------------------------------- - // Send a requtest the server requesting the current time. - //---------------------------------------------------------------------- - char data[1024]; - sprintf(data,"%s","Hello!"); - int len = strlen(data); - data[len]=0; - len++; - if (socket.Send((const uint8 *)data, len)) - { - //---------------------------------------------------------------------- - // Receive response from the server. - //---------------------------------------------------------------------- - int rec = socket.Receive(len); - if (rec) - { - uint8* data = socket.GetData(); - memcpy(&time, data, len); - printf("%s\n", time); - } + if (socket.Open("192.168.86.196", 6667)) + { + for (int i=0;i<100;i++) + { + //---------------------------------------------------------------------- + // Send a requtest the server requesting the current time. + //---------------------------------------------------------------------- + char data[1024]; + sprintf(data,"%s %d","Hello",i); + int len = strlen(data); + data[len]=0; + printf("Sending [%s]\n",data); + len++; + if (socket.Send((const uint8 *)data, len)) + { + //---------------------------------------------------------------------- + // Receive response from the server. + //---------------------------------------------------------------------- + int rec = socket.Receive(len); + if (rec) + { + uint8* data = socket.GetData(); + memcpy(&time, data, len); + printf("Received: [%s]\n", time); + } + } + } //---------------------------------------------------------------------- // Close the connection. //---------------------------------------------------------------------- socket.Close(); } - } return 1; diff --git a/test/clsocket/premake4.lua b/test/clsocket/premake4.lua index 530cbdb90..4c5b742cf 100644 --- a/test/clsocket/premake4.lua +++ b/test/clsocket/premake4.lua @@ -13,8 +13,10 @@ project ("Test_clsocket_EchoServer") links {"Ws2_32","Winmm"} end if os.is("Linux") then + defines {"_LINUX"} end if os.is("MacOSX") then + defines {"_DARWIN"} end links {"clsocket"} @@ -38,11 +40,14 @@ project ("Test_clsocket_QueryDayTime") defines { "WIN32" } links {"Ws2_32","Winmm"} end + if os.is("Linux") then - end - if os.is("MacOSX") then - end - + defines {"_LINUX"} + end + if os.is("MacOSX") then + defines {"_DARWIN"} + end + links {"clsocket"} files { From 55361e262ea5f56f493bb9cea37a21ae5146fbef Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 20 Feb 2017 13:18:33 -0800 Subject: [PATCH 07/12] fix 6dof sensors for fixed joints (recent bug left fields uninitialized in getJointInfo) add premake build support for Test_PhysicsClientUDP --- examples/SharedMemory/PhysicsClientC_API.cpp | 18 ++++--- examples/SharedMemory/udp/main.cpp | 4 +- test/SharedMemory/premake4.lua | 52 ++++++++++++++++++++ test/SharedMemory/test.c | 1 + 4 files changed, 68 insertions(+), 7 deletions(-) diff --git a/examples/SharedMemory/PhysicsClientC_API.cpp b/examples/SharedMemory/PhysicsClientC_API.cpp index 4e5b4982b..b116999d6 100644 --- a/examples/SharedMemory/PhysicsClientC_API.cpp +++ b/examples/SharedMemory/PhysicsClientC_API.cpp @@ -558,12 +558,18 @@ int b3GetJointState(b3PhysicsClientHandle physClient, b3SharedMemoryStatusHandle { state->m_jointPosition = status->m_sendActualStateArgs.m_actualStateQ[info.m_qIndex]; state->m_jointVelocity = status->m_sendActualStateArgs.m_actualStateQdot[info.m_uIndex]; - for (int ii(0); ii < 6; ++ii) { - state->m_jointForceTorque[ii] = status->m_sendActualStateArgs.m_jointReactionForces[6 * jointIndex + ii]; - } - state->m_jointMotorTorque = status->m_sendActualStateArgs.m_jointMotorForce[jointIndex]; - return 1; - } + } else + { + state->m_jointPosition=0; + state->m_jointVelocity=0; + } + for (int ii(0); ii < 6; ++ii) + { + state->m_jointForceTorque[ii] = status->m_sendActualStateArgs.m_jointReactionForces[6 * jointIndex + ii]; + } + state->m_jointMotorTorque = status->m_sendActualStateArgs.m_jointMotorForce[jointIndex]; + return 1; + } } return 0; diff --git a/examples/SharedMemory/udp/main.cpp b/examples/SharedMemory/udp/main.cpp index 3a3f07ac7..de83fb56b 100644 --- a/examples/SharedMemory/udp/main.cpp +++ b/examples/SharedMemory/udp/main.cpp @@ -133,9 +133,11 @@ int main(int argc, char *argv[]) { if (gVerboseNetworkMessagesServer) { + int dataLen = (int)event.packet->dataLength; + printf("A packet of length %u containing '%s' was " "received from %s on channel %u.\n", - event.packet->dataLength, + dataLen, event.packet->data, event.peer->data, event.channelID); diff --git a/test/SharedMemory/premake4.lua b/test/SharedMemory/premake4.lua index 3f060285a..b886a9650 100644 --- a/test/SharedMemory/premake4.lua +++ b/test/SharedMemory/premake4.lua @@ -28,6 +28,58 @@ project ("Test_SharedMemoryPhysicsClient") "../../examples/Utils/b3ResourcePath.cpp", "../../examples/Utils/b3ResourcePath.h", } + +project ("Test_PhysicsClientUDP") + + language "C++" + kind "ConsoleApp" + + includedirs { + "../../src", + "../../examples", + "../../examples/ThirdPartyLibs/enet/include" + } + links { + "enet", + "BulletFileLoader", + "Bullet3Common", + "LinearMath" + } + if os.is("Windows") then + defines { "WIN32" } + links {"Ws2_32","Winmm"} + end + + defines {"PHYSICS_UDP"} + + files { + "test.c", + "../../examples/SharedMemory/PhysicsClient.cpp", + "../../examples/SharedMemory/PhysicsClient.h", + "../../examples/SharedMemory/PhysicsClientSharedMemory.cpp", + "../../examples/SharedMemory/PhysicsClientSharedMemory.h", + "../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp", + "../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.h", + "../../examples/SharedMemory/PhysicsClientUDP.cpp", + "../../examples/SharedMemory/PhysicsClientUDP.h", + "../../examples/SharedMemory/PhysicsClientUDP_C_API.cpp", + "../../examples/SharedMemory/PhysicsClientUDP_C_API.h", + "../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.h", + "../../examples/SharedMemory/PhysicsClientC_API.cpp", + "../../examples/SharedMemory/PhysicsClientC_API.h", + "../../examples/SharedMemory/Win32SharedMemory.cpp", + "../../examples/SharedMemory/Win32SharedMemory.h", + "../../examples/SharedMemory/PosixSharedMemory.cpp", + "../../examples/SharedMemory/PosixSharedMemory.h", + "../../examples/Utils/b3ResourcePath.cpp", + "../../examples/Utils/b3ResourcePath.h", + "../../examples/SharedMemory/PhysicsDirect.cpp", + "../../examples/Utils/b3Clock.cpp", + "../../examples/MultiThreading/b3PosixThreadSupport.cpp", + "../../examples/MultiThreading/b3Win32ThreadSupport.cpp", + "../../examples/MultiThreading/b3ThreadSupportInterface.cpp", + } + project ("Test_PhysicsServerLoopBack") diff --git a/test/SharedMemory/test.c b/test/SharedMemory/test.c index f7eeb18ad..211daf0df 100644 --- a/test/SharedMemory/test.c +++ b/test/SharedMemory/test.c @@ -256,6 +256,7 @@ void testSharedMemory(b3PhysicsClientHandle sm) b3RequestCameraImageSetPixelResolution(command, width, height); statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command); } + if (b3CanSubmitCommand(sm)) { b3SharedMemoryStatusHandle state = b3SubmitClientCommandAndWaitStatus(sm, b3RequestActualStateCommandInit(sm,bodyIndex)); From bfcdb8c4081429600345e11f601c4163dcd7d738 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 20 Feb 2017 14:43:01 -0800 Subject: [PATCH 08/12] add App_PhysicsServerTCP and App_PhysicsServerSharedMemoryBridgeTCP (can be easier tunneled over SSH) --- examples/SharedMemory/premake4.lua | 2 + examples/SharedMemory/tcp/main.cpp | 223 +++++++++++++++++++++++++ examples/SharedMemory/tcp/premake4.lua | 141 ++++++++++++++++ 3 files changed, 366 insertions(+) create mode 100644 examples/SharedMemory/tcp/main.cpp create mode 100644 examples/SharedMemory/tcp/premake4.lua diff --git a/examples/SharedMemory/premake4.lua b/examples/SharedMemory/premake4.lua index 399cf1473..6ab6ad0fe 100644 --- a/examples/SharedMemory/premake4.lua +++ b/examples/SharedMemory/premake4.lua @@ -367,3 +367,5 @@ end include "udp" +include "tcp" + diff --git a/examples/SharedMemory/tcp/main.cpp b/examples/SharedMemory/tcp/main.cpp new file mode 100644 index 000000000..497766f08 --- /dev/null +++ b/examples/SharedMemory/tcp/main.cpp @@ -0,0 +1,223 @@ +#include "PassiveSocket.h" // Include header for active socket object definition + +#include +#include "../../CommonInterfaces/CommonGUIHelperInterface.h" +#include "Bullet3Common/b3CommandLineArgs.h" + +#ifdef NO_SHARED_MEMORY +#include "PhysicsServerCommandProcessor.h" +typedef PhysicsServerCommandProcessor MyCommandProcessor; +#else +#include "SharedMemoryCommandProcessor.h" +typedef SharedMemoryCommandProcessor MyCommandProcessor; +#endif //NO_SHARED_MEMORY + +#include "SharedMemoryCommands.h" +#include "Bullet3Common/b3AlignedObjectArray.h" +#include "PhysicsServerCommandProcessor.h" +#include "../Utils/b3Clock.h" + +#define MAX_PACKET 4096 + +bool gVerboseNetworkMessagesServer = true; + +void MySerializeInt(unsigned int sz, unsigned char* output) +{ + unsigned int tmp = sz; + output[0] = tmp & 255; + tmp = tmp >> 8; + output[1] = tmp & 255; + tmp = tmp >> 8; + output[2] = tmp & 255; + tmp = tmp >> 8; + output[3] = tmp & 255; +} + +int main(int argc, char *argv[]) +{ + + b3CommandLineArgs parseArgs(argc,argv); + b3Clock clock; + double timeOutInSeconds = 10; + + DummyGUIHelper guiHelper; + MyCommandProcessor* sm = new MyCommandProcessor; + sm->setGuiHelper(&guiHelper); + + int port = 6667; + if (parseArgs.GetCmdLineArgument("port",port)) + { + printf("Using TCP port %d\n", port); + } + + gVerboseNetworkMessagesServer = parseArgs.CheckCmdLineFlag("verbose"); + +#ifndef NO_SHARED_MEMORY + int key = 0; + if (parseArgs.GetCmdLineArgument("sharedMemoryKey",key)) + { + sm->setSharedMemoryKey(key); + } +#endif//NO_SHARED_MEMORY + + bool isPhysicsClientConnected = sm->connect(); + bool exitRequested = false; + + if (isPhysicsClientConnected) + { + + CPassiveSocket socket; + CActiveSocket *pClient = NULL; + + //-------------------------------------------------------------------------- + // Initialize our socket object + //-------------------------------------------------------------------------- + socket.Initialize(); + + socket.Listen("localhost", port); + + while (!exitRequested) + { + b3Clock::usleep(0); + + if ((pClient = socket.Accept()) != NULL) + { + int clientPort = socket.GetClientPort(); + printf("connected from %s:%d\n", socket.GetClientAddr(),clientPort); + + //---------------------------------------------------------------------- + // Receive request from the client. + //---------------------------------------------------------------------- + while (1) + { + //printf("try receive\n"); + bool receivedData = false; + + if (pClient->Receive(MAX_PACKET)) + { + char* msg = (char*) pClient->GetData(); + int numBytesRec = pClient->GetBytesReceived(); + if (gVerboseNetworkMessagesServer) + { + printf("received message length [%d]\n",numBytesRec); + } + + receivedData = true; + + if (strncmp(msg,"stop",4)==0) + { + printf("Stop request received\n"); + exitRequested = true; + break; + } + + + SharedMemoryCommand cmd; + + SharedMemoryCommand* cmdPtr = 0; + + //performance test + if (numBytesRec == sizeof(int)) + { + cmdPtr = &cmd; + cmd.m_type = *(int*)pClient->GetData(); + } + + if (numBytesRec == sizeof(SharedMemoryCommand)) + { + cmdPtr = (SharedMemoryCommand*)pClient->GetData(); + } + if (cmdPtr) + { + SharedMemoryStatus serverStatus; + b3AlignedObjectArray buffer; + buffer.resize(SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); + + bool hasStatus = sm->processCommand(*cmdPtr,serverStatus, &buffer[0], buffer.size()); + + double startTimeSeconds = clock.getTimeInSeconds(); + double curTimeSeconds = clock.getTimeInSeconds(); + + while ((!hasStatus) && ((curTimeSeconds - startTimeSeconds) receiveStatus(serverStatus, &buffer[0], buffer.size()); + curTimeSeconds = clock.getTimeInSeconds(); + } + if (gVerboseNetworkMessagesServer) + { + printf("buffer.size = %d\n", buffer.size()); + printf("serverStatus.m_numDataStreamBytes = %d\n", serverStatus.m_numDataStreamBytes); + } + if (hasStatus) + { + b3AlignedObjectArray packetData; + unsigned char* statBytes = (unsigned char*)&serverStatus; + + if (cmdPtr->m_type == CMD_STEP_FORWARD_SIMULATION) + { + packetData.resize(4 + sizeof(int)); + int sz = packetData.size(); + int curPos = 0; + + MySerializeInt(sz, &packetData[curPos]); + curPos += 4; + for (int i = 0; i < sizeof(int); i++) + { + packetData[i + curPos] = statBytes[i]; + } + curPos += sizeof(int); + + pClient->Send( &packetData[0], packetData.size() ); + + } + else + { + //create packetData with [int packetSizeInBytes, status, streamBytes) + packetData.resize(4 + sizeof(SharedMemoryStatus) + serverStatus.m_numDataStreamBytes); + int sz = packetData.size(); + int curPos = 0; + + MySerializeInt(sz, &packetData[curPos]); + curPos += 4; + for (int i = 0; i < sizeof(SharedMemoryStatus); i++) + { + packetData[i + curPos] = statBytes[i]; + } + curPos += sizeof(SharedMemoryStatus); + + for (int i = 0; i < serverStatus.m_numDataStreamBytes; i++) + { + packetData[i + curPos] = buffer[i]; + } + + pClient->Send( &packetData[0], packetData.size() ); + } + } + } + else + { + printf("received packet with unknown contents\n"); + } + } + if (!receivedData) + { + printf("Didn't receive data.\n"); + break; + } + } + printf("Disconnecting client.\n"); + pClient->Close(); + delete pClient; + + } + } + + socket.Close(); + socket.Shutdown(CSimpleSocket::Both); + } + + delete sm; + + return 0; +} + diff --git a/examples/SharedMemory/tcp/premake4.lua b/examples/SharedMemory/tcp/premake4.lua new file mode 100644 index 000000000..f4e011a9c --- /dev/null +++ b/examples/SharedMemory/tcp/premake4.lua @@ -0,0 +1,141 @@ + +project ("App_PhysicsServerSharedMemoryBridgeTCP") + + language "C++" + + kind "ConsoleApp" + + includedirs {"../../ThirdPartyLibs/clsocket/src","../../../src",".."} + + + if os.is("Windows") then + defines { "WIN32" } + links {"Ws2_32","Winmm"} + end + if os.is("Linux") then + defines {"_LINUX"} + end + if os.is("MacOSX") then + defines {"_DARWIN"} + end + + + links { + "clsocket", + "BulletFileLoader", + "Bullet3Common", + "LinearMath" + } + + files { + "main.cpp", + "../PhysicsClient.cpp", + "../PhysicsClient.h", + "../PhysicsDirect.cpp", + "../PhysicsDirect.h", + "../PhysicsCommandProcessorInterface.h", + "../SharedMemoryCommandProcessor.cpp", + "../SharedMemoryCommandProcessor.h", + "../PhysicsClientC_API.cpp", + "../PhysicsClientC_API.h", + "../Win32SharedMemory.cpp", + "../Win32SharedMemory.h", + "../PosixSharedMemory.cpp", + "../PosixSharedMemory.h", + "../../Utils/b3ResourcePath.cpp", + "../../Utils/b3ResourcePath.h", + "../../Utils/b3Clock.cpp", + "../../Utils/b3Clock.h", + } + + +project "App_PhysicsServerTCP" + +if _OPTIONS["ios"] then + kind "WindowedApp" +else + kind "ConsoleApp" +end + +defines { "NO_SHARED_MEMORY" } + +includedirs {"..","../../../src", "../../ThirdPartyLibs","../../ThirdPartyLibs/clsocket/src"} + +links { + "clsocket","Bullet3Common","BulletInverseDynamicsUtils", "BulletInverseDynamics", "BulletDynamics","BulletCollision", "LinearMath", "BussIK" +} + + + + if os.is("Windows") then + defines { "WIN32" } + links {"Ws2_32","Winmm"} + end + if os.is("Linux") then + defines {"_LINUX"} + end + if os.is("MacOSX") then + defines {"_DARWIN"} + end + +language "C++" + +myfiles = +{ + "../IKTrajectoryHelper.cpp", + "../IKTrajectoryHelper.h", + "../SharedMemoryCommands.h", + "../SharedMemoryPublic.h", + "../PhysicsServerCommandProcessor.cpp", + "../PhysicsServerCommandProcessor.h", + "../TinyRendererVisualShapeConverter.cpp", + "../TinyRendererVisualShapeConverter.h", + "../../TinyRenderer/geometry.cpp", + "../../TinyRenderer/model.cpp", + "../../TinyRenderer/tgaimage.cpp", + "../../TinyRenderer/our_gl.cpp", + "../../TinyRenderer/TinyRenderer.cpp", + "../../OpenGLWindow/SimpleCamera.cpp", + "../../OpenGLWindow/SimpleCamera.h", + "../../Importers/ImportURDFDemo/ConvertRigidBodies2MultiBody.h", + "../../Importers/ImportURDFDemo/MultiBodyCreationInterface.h", + "../../Importers/ImportURDFDemo/MyMultiBodyCreator.cpp", + "../../Importers/ImportURDFDemo/MyMultiBodyCreator.h", + "../../Importers/ImportMJCFDemo/BulletMJCFImporter.cpp", + "../../Importers/ImportMJCFDemo/BulletMJCFImporter.h", + "../../Importers/ImportURDFDemo/BulletUrdfImporter.cpp", + "../../Importers/ImportURDFDemo/BulletUrdfImporter.h", + "../../Importers/ImportURDFDemo/UrdfParser.cpp", + "../../Importers/ImportURDFDemo/urdfStringSplit.cpp", + "../../Importers/ImportURDFDemo/UrdfParser.cpp", + "../../Importers/ImportURDFDemo/UrdfParser.h", + "../../Importers/ImportURDFDemo/URDF2Bullet.cpp", + "../../Importers/ImportURDFDemo/URDF2Bullet.h", + "../../Utils/b3ResourcePath.cpp", + "../../Utils/b3Clock.cpp", + "../../Utils/RobotLoggingUtil.cpp", + "../../Utils/RobotLoggingUtil.h", + "../../../Extras/Serialize/BulletWorldImporter/*", + "../../../Extras/Serialize/BulletFileLoader/*", + "../../Importers/ImportURDFDemo/URDFImporterInterface.h", + "../../Importers/ImportURDFDemo/URDFJointTypes.h", + "../../Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp", + "../../Importers/ImportObjDemo/LoadMeshFromObj.cpp", + "../../Importers/ImportSTLDemo/ImportSTLSetup.h", + "../../Importers/ImportSTLDemo/LoadMeshFromSTL.h", + "../../Importers/ImportColladaDemo/LoadMeshFromCollada.cpp", + "../../Importers/ImportColladaDemo/ColladaGraphicsInstance.h", + "../../ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp", + "../../ThirdPartyLibs/tinyxml/tinystr.cpp", + "../../ThirdPartyLibs/tinyxml/tinyxml.cpp", + "../../ThirdPartyLibs/tinyxml/tinyxmlerror.cpp", + "../../ThirdPartyLibs/tinyxml/tinyxmlparser.cpp", + "../../Importers/ImportMeshUtility/b3ImportMeshUtility.cpp", + "../../ThirdPartyLibs/stb_image/stb_image.cpp", +} + +files { + myfiles, + "main.cpp", +} + From 3d73a9d788c462a6e7c4c87e38d9b9861782f474 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 20 Feb 2017 16:46:25 -0800 Subject: [PATCH 09/12] shmem preliminary TCP implementation (not working yet) --- examples/SharedMemory/PhysicsClientTCP.cpp | 496 ++++++++++++++++++ examples/SharedMemory/PhysicsClientTCP.h | 37 ++ .../SharedMemory/PhysicsClientTCP_C_API.cpp | 29 + .../SharedMemory/PhysicsClientTCP_C_API.h | 19 + examples/pybullet/premake4.lua | 26 + test/SharedMemory/premake4.lua | 62 +++ test/SharedMemory/test.c | 8 + 7 files changed, 677 insertions(+) create mode 100644 examples/SharedMemory/PhysicsClientTCP.cpp create mode 100644 examples/SharedMemory/PhysicsClientTCP.h create mode 100644 examples/SharedMemory/PhysicsClientTCP_C_API.cpp create mode 100644 examples/SharedMemory/PhysicsClientTCP_C_API.h diff --git a/examples/SharedMemory/PhysicsClientTCP.cpp b/examples/SharedMemory/PhysicsClientTCP.cpp new file mode 100644 index 000000000..35fc08964 --- /dev/null +++ b/examples/SharedMemory/PhysicsClientTCP.cpp @@ -0,0 +1,496 @@ +#include "PhysicsClientTCP.h" + +#include "ActiveSocket.h" + +#include +#include +#include "../Utils/b3Clock.h" +#include "PhysicsClient.h" +//#include "LinearMath/btVector3.h" +#include "SharedMemoryCommands.h" +#include +#include "Bullet3Common/b3Logging.h" +#include "../MultiThreading/b3ThreadSupportInterface.h" +void TCPThreadFunc(void* userPtr, void* lsMemory); +void* TCPlsMemoryFunc(); +bool gVerboseNetworkMessagesClient2 = false; + +#ifndef _WIN32 +#include "../MultiThreading/b3PosixThreadSupport.h" + +b3ThreadSupportInterface* createTCPThreadSupport(int numThreads) +{ + b3PosixThreadSupport::ThreadConstructionInfo constructionInfo("TCPThread", + TCPThreadFunc, + TCPlsMemoryFunc, + numThreads); + b3ThreadSupportInterface* threadSupport = new b3PosixThreadSupport(constructionInfo); + + return threadSupport; + +} + + +#elif defined( _WIN32) +#include "../MultiThreading/b3Win32ThreadSupport.h" + +b3ThreadSupportInterface* createTCPThreadSupport(int numThreads) +{ + b3Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("TCPThread", TCPThreadFunc, TCPlsMemoryFunc, numThreads); + b3Win32ThreadSupport* threadSupport = new b3Win32ThreadSupport(threadConstructionInfo); + return threadSupport; + +} +#endif + + + +struct TCPThreadLocalStorage +{ + int threadId; +}; + + + +unsigned int b3DeserializeInt2(const unsigned char* input) +{ + unsigned int tmp = (input[3] << 24) + (input[2] << 16) + (input[1] << 8) + input[0]; + return tmp; +} + +struct TcpNetworkedInternalData +{ + /* + ENetHost* m_client; + ENetAddress m_address; + ENetPeer* m_peer; + ENetEvent m_event; + */ + CActiveSocket m_tcpSocket; + + bool m_isConnected; + + b3ThreadSupportInterface* m_threadSupport; + + b3CriticalSection* m_cs; + + TcpNetworkedInternalData* m_tcpInternalData; + + + SharedMemoryCommand m_clientCmd; + bool m_hasCommand; + + bool m_hasStatus; + SharedMemoryStatus m_lastStatus; + b3AlignedObjectArray m_stream; + + std::string m_hostName; + int m_port; + + TcpNetworkedInternalData() + : + m_isConnected(false), + m_threadSupport(0), + m_hasCommand(false), + m_hasStatus(false) + { + + } + + bool connectTCP() + { + if (m_isConnected) + return true; + + m_tcpSocket.Initialize(); + + m_isConnected = m_tcpSocket.Open(m_hostName.c_str(),m_port); + + m_isConnected = true; + return m_isConnected; + } + + bool checkData() + { + bool hasStatus = false; + + //int serviceResult = enet_host_service(m_client, &m_event, 0); + int maxLen = 4 + sizeof(SharedMemoryStatus)+SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE; + + int recBytes = m_tcpSocket.Receive(maxLen); + + if (gVerboseNetworkMessagesClient2) + { + printf("A packet of length %d bytes received\n", recBytes); + } + + unsigned char* data = (unsigned char*)m_tcpSocket.GetData(); + + int packetSizeInBytes = b3DeserializeInt2(data); + + if (packetSizeInBytes == recBytes) + { + + SharedMemoryStatus* statPtr = (SharedMemoryStatus*)&data[4]; + if (statPtr->m_type == CMD_STEP_FORWARD_SIMULATION_COMPLETED) + { + SharedMemoryStatus dummy; + dummy.m_type = CMD_STEP_FORWARD_SIMULATION_COMPLETED; + m_lastStatus = dummy; + m_stream.resize(0); + } + else + { + + m_lastStatus = *statPtr; + int streamOffsetInBytes = 4 + sizeof(SharedMemoryStatus); + int numStreamBytes = packetSizeInBytes - streamOffsetInBytes; + m_stream.resize(numStreamBytes); + for (int i = 0; i < numStreamBytes; i++) + { + m_stream[i] = data[i + streamOffsetInBytes]; + } + } + } + else + { + printf("unknown status message received\n"); + } + + return hasStatus; + } + +}; + +enum TCPThreadEnums +{ + eTCPRequestTerminate = 13, + eTCPIsUnInitialized, + eTCPIsInitialized, + eTCPInitializationFailed, + eTCPHasTerminated +}; + + + +enum TCPCommandEnums +{ + eTCPIdle = 13, + eTCP_ConnectRequest, + eTCP_Connected, + eTCP_ConnectionFailed, + eTCP_DisconnectRequest, + eTCP_Disconnected, + +}; + +void TCPThreadFunc(void* userPtr, void* lsMemory) +{ + printf("TCPThreadFunc thread started\n"); + + TcpNetworkedInternalData* args = (TcpNetworkedInternalData*)userPtr; +// int workLeft = true; + b3Clock clock; + clock.reset(); + bool init = true; + if (init) + { + + args->m_cs->lock(); + args->m_cs->setSharedParam(0, eTCPIsInitialized); + args->m_cs->unlock(); + + + double deltaTimeInSeconds = 0; + + do + { + b3Clock::usleep(0); + + deltaTimeInSeconds += double(clock.getTimeMicroseconds()) / 1000000.; + + { + + clock.reset(); + deltaTimeInSeconds = 0.f; + switch (args->m_cs->getSharedParam(1)) + { + case eTCP_ConnectRequest: + { + bool connected = args->connectTCP(); + if (connected) + { + args->m_cs->setSharedParam(1, eTCP_Connected); + } + else + { + args->m_cs->setSharedParam(1, eTCP_ConnectionFailed); + } + break; + } + default: + { + } + }; + + if (args->m_isConnected) + { + + args->m_cs->lock(); + bool hasCommand = args->m_hasCommand; + args->m_cs->unlock(); + + + if (hasCommand) + { + int sz = 0; + unsigned char* data = 0; + + + if (args->m_clientCmd.m_type == CMD_STEP_FORWARD_SIMULATION) + { + sz = sizeof(int); + data = (unsigned char*) &args->m_clientCmd.m_type; + } + else + { + sz = sizeof(SharedMemoryCommand); + data = (unsigned char*)&args->m_clientCmd; + } + int res; + + args->m_tcpSocket.Send((const uint8 *)data,sz); + + args->m_cs->lock(); + args->m_hasCommand = false; + args->m_cs->unlock(); + } + + + bool hasNewStatus = args->checkData(); + if (hasNewStatus) + { + if (args->m_hasStatus) + { + //overflow: last status hasn't been processed yet + b3Assert(0); + printf("Error: received new status but previous status not processed yet"); + } + else + { + args->m_cs->lock(); + args->m_hasStatus = hasNewStatus; + args->m_cs->unlock(); + } + } + } + + } + + } while (args->m_cs->getSharedParam(0) != eTCPRequestTerminate); + } + else + { + args->m_cs->lock(); + args->m_cs->setSharedParam(0, eTCPInitializationFailed); + args->m_cs->unlock(); + } + + + printf("finished\n"); + +} + + + +void* TCPlsMemoryFunc() +{ + //don't create local store memory, just return 0 + return new TCPThreadLocalStorage; +} + + + + + + + +TcpNetworkedPhysicsProcessor::TcpNetworkedPhysicsProcessor(const char* hostName, int port) +{ + m_data = new TcpNetworkedInternalData; + if (hostName) + { + m_data->m_hostName = hostName; + } + m_data->m_port = port; + +} + +TcpNetworkedPhysicsProcessor::~TcpNetworkedPhysicsProcessor() +{ + disconnect(); + delete m_data; +} + +bool TcpNetworkedPhysicsProcessor::processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes) +{ + if(gVerboseNetworkMessagesClient2) + { + printf("PhysicsClientTCP::processCommand\n"); + } +// int sz = sizeof(SharedMemoryCommand); + int timeout = 1024 * 1024 * 1024; + + m_data->m_cs->lock(); + m_data->m_clientCmd = clientCmd; + m_data->m_hasCommand = true; + m_data->m_cs->unlock(); + + while (m_data->m_hasCommand && (timeout-- > 0)) + { + b3Clock::usleep(0); + } + +#if 0 + + timeout = 1024 * 1024 * 1024; + + bool hasStatus = false; + + const SharedMemoryStatus* stat = 0; + while ((!hasStatus) && (timeout-- > 0)) + { + hasStatus = receiveStatus(serverStatusOut, bufferServerToClient, bufferSizeInBytes); + b3Clock::usleep(100); + } + return hasStatus; + +#endif + + return false; +} + +bool TcpNetworkedPhysicsProcessor::receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes) +{ + bool hasStatus = false; + if (m_data->m_hasStatus) + { + if (gVerboseNetworkMessagesClient2) + { + printf("TcpNetworkedPhysicsProcessor::receiveStatus\n"); + } + + hasStatus = true; + serverStatusOut = m_data->m_lastStatus; + int numStreamBytes = m_data->m_stream.size(); + + if (numStreamBytes < bufferSizeInBytes) + { + for (int i = 0; i < numStreamBytes; i++) + { + bufferServerToClient[i] = m_data->m_stream[i]; + } + } + else + { + printf("Error: steam buffer overflow\n"); + } + + m_data->m_cs->lock(); + m_data->m_hasStatus = false; + m_data->m_cs->unlock(); + } + + + return hasStatus; + +} + + +void TcpNetworkedPhysicsProcessor::renderScene() +{ +} + +void TcpNetworkedPhysicsProcessor::physicsDebugDraw(int debugDrawFlags) +{ +} + +void TcpNetworkedPhysicsProcessor::setGuiHelper(struct GUIHelperInterface* guiHelper) +{ +} + +bool TcpNetworkedPhysicsProcessor::isConnected() const +{ + return m_data->m_isConnected; +} + + +bool TcpNetworkedPhysicsProcessor::connect() +{ + if (m_data->m_threadSupport==0) + { + m_data->m_threadSupport = createTCPThreadSupport(1); + + m_data->m_cs = m_data->m_threadSupport->createCriticalSection(); + m_data->m_cs->setSharedParam(0, eTCPIsUnInitialized); + m_data->m_threadSupport->runTask(B3_THREAD_SCHEDULE_TASK, (void*) m_data, 0); + + while (m_data->m_cs->getSharedParam(0) == eTCPIsUnInitialized) + { + b3Clock::usleep(1000); + } + + m_data->m_cs->lock(); + m_data->m_cs->setSharedParam(1, eTCP_ConnectRequest); + m_data->m_cs->unlock(); + + while (m_data->m_cs->getSharedParam(1) == eTCP_ConnectRequest) + { + b3Clock::usleep(1000); + } + + } + unsigned int sharedParam = m_data->m_cs->getSharedParam(1); + bool isConnected = (sharedParam == eTCP_Connected); + return isConnected; +} + +void TcpNetworkedPhysicsProcessor::disconnect() +{ + if (m_data->m_threadSupport) + { + m_data->m_cs->lock(); + m_data->m_cs->setSharedParam(0, eTCPRequestTerminate); + m_data->m_cs->unlock(); + + int numActiveThreads = 1; + + while (numActiveThreads) + { + int arg0, arg1; + if (m_data->m_threadSupport->isTaskCompleted(&arg0, &arg1, 0)) + { + numActiveThreads--; + printf("numActiveThreads = %d\n", numActiveThreads); + } + else + { + b3Clock::usleep(1000); + } + }; + + printf("stopping threads\n"); + + delete m_data->m_threadSupport; + m_data->m_threadSupport = 0; + m_data->m_isConnected = false; + } + + + +} + + + + + diff --git a/examples/SharedMemory/PhysicsClientTCP.h b/examples/SharedMemory/PhysicsClientTCP.h new file mode 100644 index 000000000..26dd45b58 --- /dev/null +++ b/examples/SharedMemory/PhysicsClientTCP.h @@ -0,0 +1,37 @@ +#ifndef PHYSICS_CLIENT_TCP_H +#define PHYSICS_CLIENT_TCP_H + +#include "PhysicsDirect.h" +#include "PhysicsServerCommandProcessor.h" + +class TcpNetworkedPhysicsProcessor : public PhysicsCommandProcessorInterface +{ + + struct TcpNetworkedInternalData* m_data; + +public: + TcpNetworkedPhysicsProcessor(const char* hostName, int port); + + virtual ~TcpNetworkedPhysicsProcessor(); + + virtual bool connect(); + + virtual void disconnect(); + + virtual bool isConnected() const; + + virtual bool processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes); + + virtual bool receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes); + + virtual void renderScene(); + + virtual void physicsDebugDraw(int debugDrawFlags); + + virtual void setGuiHelper(struct GUIHelperInterface* guiHelper); + +}; + + +#endif //PHYSICS_CLIENT_TCP_H + diff --git a/examples/SharedMemory/PhysicsClientTCP_C_API.cpp b/examples/SharedMemory/PhysicsClientTCP_C_API.cpp new file mode 100644 index 000000000..e333b967a --- /dev/null +++ b/examples/SharedMemory/PhysicsClientTCP_C_API.cpp @@ -0,0 +1,29 @@ + +#include "PhysicsClientTCP_C_API.h" +#include "PhysicsClientTCP.h" +#include "PhysicsDirect.h" +#include + +b3PhysicsClientHandle b3ConnectPhysicsTCP(const char* hostName, int port) +{ + + TcpNetworkedPhysicsProcessor* tcp = new TcpNetworkedPhysicsProcessor(hostName, port); + + PhysicsDirect* direct = new PhysicsDirect(tcp, true); + + bool connected; + connected = direct->connect(); + if (connected) + { + printf("b3ConnectPhysicsTCP connected successfully.\n"); + } + else + { + printf("b3ConnectPhysicsTCP connection failed.\n"); + + } + return (b3PhysicsClientHandle)direct; +} + + + diff --git a/examples/SharedMemory/PhysicsClientTCP_C_API.h b/examples/SharedMemory/PhysicsClientTCP_C_API.h new file mode 100644 index 000000000..dee180377 --- /dev/null +++ b/examples/SharedMemory/PhysicsClientTCP_C_API.h @@ -0,0 +1,19 @@ +#ifndef PHYSICS_CLIENT_TCP_C_API_H +#define PHYSICS_CLIENT_TCP_C_API_H + +#include "PhysicsClientC_API.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + ///send physics commands using TCP networking + b3PhysicsClientHandle b3ConnectPhysicsTCP(const char* hostName, int port); + + +#ifdef __cplusplus +} +#endif + +#endif //PHYSICS_CLIENT_TCP_C_API_H diff --git a/examples/pybullet/premake4.lua b/examples/pybullet/premake4.lua index a47016c8b..d424ef209 100644 --- a/examples/pybullet/premake4.lua +++ b/examples/pybullet/premake4.lua @@ -59,6 +59,32 @@ if not _OPTIONS["no-enet"] then defines {"BT_ENABLE_ENET"} end + if not _OPTIONS["no-clsocket"] then + + includedirs {"../../examples/ThirdPartyLibs/clsocket/src"} + + if os.is("Windows") then + defines { "WIN32" } + links {"Ws2_32","Winmm"} + end + if os.is("Linux") then + defines {"_LINUX"} + end + if os.is("MacOSX") then + defines {"_DARWIN"} + end + + links {"clsocket"} + + files { + "../../examples/SharedMemory/PhysicsClientTCP.cpp", + "../../examples/SharedMemory/PhysicsClientTCP.h", + "../../examples/SharedMemory/PhysicsClientTCP_C_API.cpp", + "../../examples/SharedMemory/PhysicsClientTCP_C_API.h", + } + defines {"BT_ENABLE_CLSOCKET"} + end + files { "pybullet.c", diff --git a/test/SharedMemory/premake4.lua b/test/SharedMemory/premake4.lua index b886a9650..cfe86780e 100644 --- a/test/SharedMemory/premake4.lua +++ b/test/SharedMemory/premake4.lua @@ -80,6 +80,68 @@ project ("Test_PhysicsClientUDP") "../../examples/MultiThreading/b3ThreadSupportInterface.cpp", } + +project ("Test_PhysicsClientTCP") + + language "C++" + kind "ConsoleApp" + + includedirs { + "../../src", + "../../examples", + "../../examples/ThirdPartyLibs/clsocket/src" + } + links { + "clsocket", + "BulletFileLoader", + "Bullet3Common", + "LinearMath" + } + if os.is("Windows") then + defines { "WIN32" } + links {"Ws2_32","Winmm"} + end + + if os.is("Windows") then + defines { "WIN32","_WINSOCK_DEPRECATED_NO_WARNINGS" } + end + if os.is("Linux") then + defines {"_LINUX"} + end + if os.is("MacOSX") then + defines {"_DARWIN"} + end + + defines {"PHYSICS_TCP"} + + files { + "test.c", + "../../examples/SharedMemory/PhysicsClient.cpp", + "../../examples/SharedMemory/PhysicsClient.h", + "../../examples/SharedMemory/PhysicsClientSharedMemory.cpp", + "../../examples/SharedMemory/PhysicsClientSharedMemory.h", + "../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp", + "../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.h", + "../../examples/SharedMemory/PhysicsClientTCP.cpp", + "../../examples/SharedMemory/PhysicsClientTCP.h", + "../../examples/SharedMemory/PhysicsClientTCP_C_API.cpp", + "../../examples/SharedMemory/PhysicsClientTCP_C_API.h", + "../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.h", + "../../examples/SharedMemory/PhysicsClientC_API.cpp", + "../../examples/SharedMemory/PhysicsClientC_API.h", + "../../examples/SharedMemory/Win32SharedMemory.cpp", + "../../examples/SharedMemory/Win32SharedMemory.h", + "../../examples/SharedMemory/PosixSharedMemory.cpp", + "../../examples/SharedMemory/PosixSharedMemory.h", + "../../examples/Utils/b3ResourcePath.cpp", + "../../examples/Utils/b3ResourcePath.h", + "../../examples/SharedMemory/PhysicsDirect.cpp", + "../../examples/Utils/b3Clock.cpp", + "../../examples/MultiThreading/b3PosixThreadSupport.cpp", + "../../examples/MultiThreading/b3Win32ThreadSupport.cpp", + "../../examples/MultiThreading/b3ThreadSupportInterface.cpp", + } + project ("Test_PhysicsServerLoopBack") diff --git a/test/SharedMemory/test.c b/test/SharedMemory/test.c index 211daf0df..e475a4705 100644 --- a/test/SharedMemory/test.c +++ b/test/SharedMemory/test.c @@ -8,6 +8,10 @@ #include "SharedMemory/PhysicsClientUDP_C_API.h" #endif//PHYSICS_UDP +#ifdef PHYSICS_TCP +#include "SharedMemory/PhysicsClientTCP_C_API.h" +#endif//PHYSICS_TCP + #ifdef PHYSICS_LOOP_BACK #include "SharedMemory/PhysicsLoopBackC_API.h" #endif //PHYSICS_LOOP_BACK @@ -345,6 +349,10 @@ int main(int argc, char* argv[]) b3PhysicsClientHandle sm = b3ConnectPhysicsUDP("localhost",1234); #endif //PHYSICS_UDP +#ifdef PHYSICS_TCP + b3PhysicsClientHandle sm = b3ConnectPhysicsTCP("localhost",6667); +#endif //PHYSICS_UDP + testSharedMemory(sm); } #endif From 942015df9dcc208d1a77280bc78fe697a7b550ac Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 20 Feb 2017 18:54:12 -0800 Subject: [PATCH 10/12] use TCP in main thread, accumulate bytes until size matches. --- examples/SharedMemory/PhysicsClientTCP.cpp | 405 +++++---------------- examples/SharedMemory/tcp/main.cpp | 196 +++++----- test/clsocket/EchoServer.cpp | 6 +- 3 files changed, 194 insertions(+), 413 deletions(-) diff --git a/examples/SharedMemory/PhysicsClientTCP.cpp b/examples/SharedMemory/PhysicsClientTCP.cpp index 35fc08964..443fc3bef 100644 --- a/examples/SharedMemory/PhysicsClientTCP.cpp +++ b/examples/SharedMemory/PhysicsClientTCP.cpp @@ -10,45 +10,7 @@ #include "SharedMemoryCommands.h" #include #include "Bullet3Common/b3Logging.h" -#include "../MultiThreading/b3ThreadSupportInterface.h" -void TCPThreadFunc(void* userPtr, void* lsMemory); -void* TCPlsMemoryFunc(); -bool gVerboseNetworkMessagesClient2 = false; - -#ifndef _WIN32 -#include "../MultiThreading/b3PosixThreadSupport.h" - -b3ThreadSupportInterface* createTCPThreadSupport(int numThreads) -{ - b3PosixThreadSupport::ThreadConstructionInfo constructionInfo("TCPThread", - TCPThreadFunc, - TCPlsMemoryFunc, - numThreads); - b3ThreadSupportInterface* threadSupport = new b3PosixThreadSupport(constructionInfo); - - return threadSupport; - -} - - -#elif defined( _WIN32) -#include "../MultiThreading/b3Win32ThreadSupport.h" - -b3ThreadSupportInterface* createTCPThreadSupport(int numThreads) -{ - b3Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("TCPThread", TCPThreadFunc, TCPlsMemoryFunc, numThreads); - b3Win32ThreadSupport* threadSupport = new b3Win32ThreadSupport(threadConstructionInfo); - return threadSupport; - -} -#endif - - - -struct TCPThreadLocalStorage -{ - int threadId; -}; +#include "Bullet3Common/b3AlignedObjectArray.h" @@ -57,6 +19,8 @@ unsigned int b3DeserializeInt2(const unsigned char* input) unsigned int tmp = (input[3] << 24) + (input[2] << 16) + (input[1] << 8) + input[0]; return tmp; } +bool gVerboseNetworkMessagesClient2 = false; + struct TcpNetworkedInternalData { @@ -70,29 +34,24 @@ struct TcpNetworkedInternalData bool m_isConnected; - b3ThreadSupportInterface* m_threadSupport; - - b3CriticalSection* m_cs; - TcpNetworkedInternalData* m_tcpInternalData; SharedMemoryCommand m_clientCmd; bool m_hasCommand; - bool m_hasStatus; SharedMemoryStatus m_lastStatus; b3AlignedObjectArray m_stream; std::string m_hostName; int m_port; + b3AlignedObjectArray m_tempBuffer; + TcpNetworkedInternalData() : m_isConnected(false), - m_threadSupport(0), - m_hasCommand(false), - m_hasStatus(false) + m_hasCommand(false) { } @@ -105,8 +64,7 @@ struct TcpNetworkedInternalData m_tcpSocket.Initialize(); m_isConnected = m_tcpSocket.Open(m_hostName.c_str(),m_port); - - m_isConnected = true; + return m_isConnected; } @@ -117,203 +75,66 @@ struct TcpNetworkedInternalData //int serviceResult = enet_host_service(m_client, &m_event, 0); int maxLen = 4 + sizeof(SharedMemoryStatus)+SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE; - int recBytes = m_tcpSocket.Receive(maxLen); + int rBytes = m_tcpSocket.Receive(maxLen); + if (rBytes<=0) + return false; - if (gVerboseNetworkMessagesClient2) - { - printf("A packet of length %d bytes received\n", recBytes); - } - - unsigned char* data = (unsigned char*)m_tcpSocket.GetData(); - - int packetSizeInBytes = b3DeserializeInt2(data); + //append to tmp buffer + //recBytes - if (packetSizeInBytes == recBytes) - { + unsigned char* d2 = (unsigned char*)m_tcpSocket.GetData(); - SharedMemoryStatus* statPtr = (SharedMemoryStatus*)&data[4]; - if (statPtr->m_type == CMD_STEP_FORWARD_SIMULATION_COMPLETED) - { - SharedMemoryStatus dummy; - dummy.m_type = CMD_STEP_FORWARD_SIMULATION_COMPLETED; - m_lastStatus = dummy; - m_stream.resize(0); - } - else - { - m_lastStatus = *statPtr; - int streamOffsetInBytes = 4 + sizeof(SharedMemoryStatus); - int numStreamBytes = packetSizeInBytes - streamOffsetInBytes; - m_stream.resize(numStreamBytes); - for (int i = 0; i < numStreamBytes; i++) - { - m_stream[i] = data[i + streamOffsetInBytes]; - } - } - } - else - { - printf("unknown status message received\n"); - } - + int curSize = m_tempBuffer.size(); + m_tempBuffer.resize(curSize+rBytes); + for (int i=0;i=4) + { + packetSizeInBytes = b3DeserializeInt2(&m_tempBuffer[0]); + } + + if (m_tempBuffer.size() == packetSizeInBytes) + { + unsigned char* data = &m_tempBuffer[0]; + if (gVerboseNetworkMessagesClient2) + { + printf("A packet of length %d bytes received\n", m_tempBuffer.size()); + } + + hasStatus = true; + SharedMemoryStatus* statPtr = (SharedMemoryStatus*)&data[4]; + if (statPtr->m_type == CMD_STEP_FORWARD_SIMULATION_COMPLETED) + { + SharedMemoryStatus dummy; + dummy.m_type = CMD_STEP_FORWARD_SIMULATION_COMPLETED; + m_lastStatus = dummy; + m_stream.resize(0); + } + else + { + + m_lastStatus = *statPtr; + int streamOffsetInBytes = 4 + sizeof(SharedMemoryStatus); + int numStreamBytes = packetSizeInBytes - streamOffsetInBytes; + m_stream.resize(numStreamBytes); + for (int i = 0; i < numStreamBytes; i++) + { + m_stream[i] = data[i + streamOffsetInBytes]; + } + } + m_tempBuffer.clear(); + } return hasStatus; } }; -enum TCPThreadEnums -{ - eTCPRequestTerminate = 13, - eTCPIsUnInitialized, - eTCPIsInitialized, - eTCPInitializationFailed, - eTCPHasTerminated -}; - - - -enum TCPCommandEnums -{ - eTCPIdle = 13, - eTCP_ConnectRequest, - eTCP_Connected, - eTCP_ConnectionFailed, - eTCP_DisconnectRequest, - eTCP_Disconnected, - -}; - -void TCPThreadFunc(void* userPtr, void* lsMemory) -{ - printf("TCPThreadFunc thread started\n"); - - TcpNetworkedInternalData* args = (TcpNetworkedInternalData*)userPtr; -// int workLeft = true; - b3Clock clock; - clock.reset(); - bool init = true; - if (init) - { - - args->m_cs->lock(); - args->m_cs->setSharedParam(0, eTCPIsInitialized); - args->m_cs->unlock(); - - - double deltaTimeInSeconds = 0; - - do - { - b3Clock::usleep(0); - - deltaTimeInSeconds += double(clock.getTimeMicroseconds()) / 1000000.; - - { - - clock.reset(); - deltaTimeInSeconds = 0.f; - switch (args->m_cs->getSharedParam(1)) - { - case eTCP_ConnectRequest: - { - bool connected = args->connectTCP(); - if (connected) - { - args->m_cs->setSharedParam(1, eTCP_Connected); - } - else - { - args->m_cs->setSharedParam(1, eTCP_ConnectionFailed); - } - break; - } - default: - { - } - }; - - if (args->m_isConnected) - { - - args->m_cs->lock(); - bool hasCommand = args->m_hasCommand; - args->m_cs->unlock(); - - - if (hasCommand) - { - int sz = 0; - unsigned char* data = 0; - - - if (args->m_clientCmd.m_type == CMD_STEP_FORWARD_SIMULATION) - { - sz = sizeof(int); - data = (unsigned char*) &args->m_clientCmd.m_type; - } - else - { - sz = sizeof(SharedMemoryCommand); - data = (unsigned char*)&args->m_clientCmd; - } - int res; - - args->m_tcpSocket.Send((const uint8 *)data,sz); - - args->m_cs->lock(); - args->m_hasCommand = false; - args->m_cs->unlock(); - } - - - bool hasNewStatus = args->checkData(); - if (hasNewStatus) - { - if (args->m_hasStatus) - { - //overflow: last status hasn't been processed yet - b3Assert(0); - printf("Error: received new status but previous status not processed yet"); - } - else - { - args->m_cs->lock(); - args->m_hasStatus = hasNewStatus; - args->m_cs->unlock(); - } - } - } - - } - - } while (args->m_cs->getSharedParam(0) != eTCPRequestTerminate); - } - else - { - args->m_cs->lock(); - args->m_cs->setSharedParam(0, eTCPInitializationFailed); - args->m_cs->unlock(); - } - - - printf("finished\n"); - -} - - - -void* TCPlsMemoryFunc() -{ - //don't create local store memory, just return 0 - return new TCPThreadLocalStorage; -} - - - - - - TcpNetworkedPhysicsProcessor::TcpNetworkedPhysicsProcessor(const char* hostName, int port) { @@ -338,49 +159,42 @@ bool TcpNetworkedPhysicsProcessor::processCommand(const struct SharedMemoryComma { printf("PhysicsClientTCP::processCommand\n"); } -// int sz = sizeof(SharedMemoryCommand); - int timeout = 1024 * 1024 * 1024; - m_data->m_cs->lock(); - m_data->m_clientCmd = clientCmd; - m_data->m_hasCommand = true; - m_data->m_cs->unlock(); - - while (m_data->m_hasCommand && (timeout-- > 0)) { - b3Clock::usleep(0); - } + int sz = 0; + unsigned char* data = 0; + m_data->m_tempBuffer.clear(); -#if 0 + if (clientCmd.m_type == CMD_STEP_FORWARD_SIMULATION) + { + sz = sizeof(int); + data = (unsigned char*) &clientCmd.m_type; + } + else + { + sz = sizeof(SharedMemoryCommand); + data = (unsigned char*)&clientCmd; + } + int res; + + m_data->m_tcpSocket.Send((const uint8 *)data,sz); - timeout = 1024 * 1024 * 1024; - - bool hasStatus = false; - - const SharedMemoryStatus* stat = 0; - while ((!hasStatus) && (timeout-- > 0)) - { - hasStatus = receiveStatus(serverStatusOut, bufferServerToClient, bufferSizeInBytes); - b3Clock::usleep(100); - } - return hasStatus; - -#endif + } return false; } bool TcpNetworkedPhysicsProcessor::receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes) { - bool hasStatus = false; - if (m_data->m_hasStatus) + bool hasStatus = m_data->checkData(); + + if (hasStatus) { if (gVerboseNetworkMessagesClient2) { printf("TcpNetworkedPhysicsProcessor::receiveStatus\n"); } - hasStatus = true; serverStatusOut = m_data->m_lastStatus; int numStreamBytes = m_data->m_stream.size(); @@ -396,9 +210,6 @@ bool TcpNetworkedPhysicsProcessor::receiveStatus(struct SharedMemoryStatus& serv printf("Error: steam buffer overflow\n"); } - m_data->m_cs->lock(); - m_data->m_hasStatus = false; - m_data->m_cs->unlock(); } @@ -427,70 +238,18 @@ bool TcpNetworkedPhysicsProcessor::isConnected() const bool TcpNetworkedPhysicsProcessor::connect() { - if (m_data->m_threadSupport==0) - { - m_data->m_threadSupport = createTCPThreadSupport(1); - - m_data->m_cs = m_data->m_threadSupport->createCriticalSection(); - m_data->m_cs->setSharedParam(0, eTCPIsUnInitialized); - m_data->m_threadSupport->runTask(B3_THREAD_SCHEDULE_TASK, (void*) m_data, 0); - - while (m_data->m_cs->getSharedParam(0) == eTCPIsUnInitialized) - { - b3Clock::usleep(1000); - } - - m_data->m_cs->lock(); - m_data->m_cs->setSharedParam(1, eTCP_ConnectRequest); - m_data->m_cs->unlock(); - - while (m_data->m_cs->getSharedParam(1) == eTCP_ConnectRequest) - { - b3Clock::usleep(1000); - } - - } - unsigned int sharedParam = m_data->m_cs->getSharedParam(1); - bool isConnected = (sharedParam == eTCP_Connected); + bool isConnected = m_data->connectTCP(); return isConnected; } void TcpNetworkedPhysicsProcessor::disconnect() { - if (m_data->m_threadSupport) - { - m_data->m_cs->lock(); - m_data->m_cs->setSharedParam(0, eTCPRequestTerminate); - m_data->m_cs->unlock(); - - int numActiveThreads = 1; - - while (numActiveThreads) - { - int arg0, arg1; - if (m_data->m_threadSupport->isTaskCompleted(&arg0, &arg1, 0)) - { - numActiveThreads--; - printf("numActiveThreads = %d\n", numActiveThreads); - } - else - { - b3Clock::usleep(1000); - } - }; - - printf("stopping threads\n"); - - delete m_data->m_threadSupport; - m_data->m_threadSupport = 0; - m_data->m_isConnected = false; - } - - - + m_data->m_tcpSocket.Close(); + m_data->m_isConnected = false; } + diff --git a/examples/SharedMemory/tcp/main.cpp b/examples/SharedMemory/tcp/main.cpp index 497766f08..efd667ed9 100644 --- a/examples/SharedMemory/tcp/main.cpp +++ b/examples/SharedMemory/tcp/main.cpp @@ -17,7 +17,6 @@ typedef SharedMemoryCommandProcessor MyCommandProcessor; #include "PhysicsServerCommandProcessor.h" #include "../Utils/b3Clock.h" -#define MAX_PACKET 4096 bool gVerboseNetworkMessagesServer = true; @@ -75,6 +74,8 @@ int main(int argc, char *argv[]) socket.Initialize(); socket.Listen("localhost", port); + + b3AlignedObjectArray bytesReceived; while (!exitRequested) { @@ -93,111 +94,130 @@ int main(int argc, char *argv[]) //printf("try receive\n"); bool receivedData = false; - if (pClient->Receive(MAX_PACKET)) + int maxLen = 4 + sizeof(SharedMemoryStatus)+SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE; + + if (pClient->Receive(maxLen)) { - char* msg = (char*) pClient->GetData(); - int numBytesRec = pClient->GetBytesReceived(); - if (gVerboseNetworkMessagesServer) - { - printf("received message length [%d]\n",numBytesRec); - } + + char* msg2 = (char*) pClient->GetData(); + int numBytesRec2 = pClient->GetBytesReceived(); + + int curSize = bytesReceived.size(); + bytesReceived.resize(bytesReceived.size()+numBytesRec2); + for (int i=0;iGetData(); - } + //performance test + if (numBytesRec == sizeof(int)) + { + cmdPtr = &cmd; + cmd.m_type = *(int*)&bytesReceived[0]; + } - if (numBytesRec == sizeof(SharedMemoryCommand)) - { - cmdPtr = (SharedMemoryCommand*)pClient->GetData(); - } - if (cmdPtr) - { - SharedMemoryStatus serverStatus; - b3AlignedObjectArray buffer; - buffer.resize(SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); + if (numBytesRec == sizeof(SharedMemoryCommand)) + { + cmdPtr = (SharedMemoryCommand*)&bytesReceived[0]; + } + if (cmdPtr) + { + SharedMemoryStatus serverStatus; + b3AlignedObjectArray buffer; + buffer.resize(SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); - bool hasStatus = sm->processCommand(*cmdPtr,serverStatus, &buffer[0], buffer.size()); + bool hasStatus = sm->processCommand(*cmdPtr,serverStatus, &buffer[0], buffer.size()); - double startTimeSeconds = clock.getTimeInSeconds(); - double curTimeSeconds = clock.getTimeInSeconds(); + double startTimeSeconds = clock.getTimeInSeconds(); + double curTimeSeconds = clock.getTimeInSeconds(); - while ((!hasStatus) && ((curTimeSeconds - startTimeSeconds) receiveStatus(serverStatus, &buffer[0], buffer.size()); - curTimeSeconds = clock.getTimeInSeconds(); - } - if (gVerboseNetworkMessagesServer) - { - printf("buffer.size = %d\n", buffer.size()); - printf("serverStatus.m_numDataStreamBytes = %d\n", serverStatus.m_numDataStreamBytes); - } - if (hasStatus) - { - b3AlignedObjectArray packetData; - unsigned char* statBytes = (unsigned char*)&serverStatus; + while ((!hasStatus) && ((curTimeSeconds - startTimeSeconds) receiveStatus(serverStatus, &buffer[0], buffer.size()); + curTimeSeconds = clock.getTimeInSeconds(); + } + if (gVerboseNetworkMessagesServer) + { + printf("buffer.size = %d\n", buffer.size()); + printf("serverStatus.m_numDataStreamBytes = %d\n", serverStatus.m_numDataStreamBytes); + } + if (hasStatus) + { + b3AlignedObjectArray packetData; + unsigned char* statBytes = (unsigned char*)&serverStatus; - if (cmdPtr->m_type == CMD_STEP_FORWARD_SIMULATION) - { - packetData.resize(4 + sizeof(int)); - int sz = packetData.size(); - int curPos = 0; + if (cmdPtr->m_type == CMD_STEP_FORWARD_SIMULATION) + { + packetData.resize(4 + sizeof(int)); + int sz = packetData.size(); + int curPos = 0; - MySerializeInt(sz, &packetData[curPos]); - curPos += 4; - for (int i = 0; i < sizeof(int); i++) - { - packetData[i + curPos] = statBytes[i]; - } - curPos += sizeof(int); + MySerializeInt(sz, &packetData[curPos]); + curPos += 4; + for (int i = 0; i < sizeof(int); i++) + { + packetData[i + curPos] = statBytes[i]; + } + curPos += sizeof(int); - pClient->Send( &packetData[0], packetData.size() ); + pClient->Send( &packetData[0], packetData.size() ); - } - else - { - //create packetData with [int packetSizeInBytes, status, streamBytes) - packetData.resize(4 + sizeof(SharedMemoryStatus) + serverStatus.m_numDataStreamBytes); - int sz = packetData.size(); - int curPos = 0; + } + else + { + //create packetData with [int packetSizeInBytes, status, streamBytes) + packetData.resize(4 + sizeof(SharedMemoryStatus) + serverStatus.m_numDataStreamBytes); + int sz = packetData.size(); + int curPos = 0; - MySerializeInt(sz, &packetData[curPos]); - curPos += 4; - for (int i = 0; i < sizeof(SharedMemoryStatus); i++) - { - packetData[i + curPos] = statBytes[i]; - } - curPos += sizeof(SharedMemoryStatus); + MySerializeInt(sz, &packetData[curPos]); + curPos += 4; + for (int i = 0; i < sizeof(SharedMemoryStatus); i++) + { + packetData[i + curPos] = statBytes[i]; + } + curPos += sizeof(SharedMemoryStatus); - for (int i = 0; i < serverStatus.m_numDataStreamBytes; i++) - { - packetData[i + curPos] = buffer[i]; - } + for (int i = 0; i < serverStatus.m_numDataStreamBytes; i++) + { + packetData[i + curPos] = buffer[i]; + } - pClient->Send( &packetData[0], packetData.size() ); - } - } - } - else - { - printf("received packet with unknown contents\n"); - } + pClient->Send( &packetData[0], packetData.size() ); + } + } + } + else + { + printf("received packet with unknown contents\n"); + } + bytesReceived.clear(); + + } } if (!receivedData) { diff --git a/test/clsocket/EchoServer.cpp b/test/clsocket/EchoServer.cpp index 74c03ac7c..4388fc2f2 100644 --- a/test/clsocket/EchoServer.cpp +++ b/test/clsocket/EchoServer.cpp @@ -28,10 +28,12 @@ int main(int argc, char **argv) { //printf("try receive\n"); bool receivedData = false; - - if (pClient->Receive(MAX_PACKET)) + int recBytes = 0; + recBytes = pClient->Receive(MAX_PACKET); + if (recBytes) { char* msg = (char*) pClient->GetData(); + msg[recBytes]=0; printf("received message [%s]\n",msg); //------------------------------------------------------------------ // Send response to client and close connection to the client. From 28146e816f4641c23af02f57fffa3fc280bc0f03 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 20 Feb 2017 20:34:05 -0800 Subject: [PATCH 11/12] export TCP connection mode to pybullet made TCP disconnection detection more reliable --- examples/SharedMemory/tcp/main.cpp | 34 ++++++++++++++---- .../clsocket/src/SimpleSocket.h | 8 +++++ examples/pybullet/CMakeLists.txt | 7 ++-- examples/pybullet/pybullet.c | 36 ++++++++++++++++--- 4 files changed, 72 insertions(+), 13 deletions(-) diff --git a/examples/SharedMemory/tcp/main.cpp b/examples/SharedMemory/tcp/main.cpp index efd667ed9..3eb0b3c02 100644 --- a/examples/SharedMemory/tcp/main.cpp +++ b/examples/SharedMemory/tcp/main.cpp @@ -74,8 +74,10 @@ int main(int argc, char *argv[]) socket.Initialize(); socket.Listen("localhost", port); - - b3AlignedObjectArray bytesReceived; + socket.SetBlocking(); + + int curNumErr = 0; + while (!exitRequested) { @@ -83,9 +85,12 @@ int main(int argc, char *argv[]) if ((pClient = socket.Accept()) != NULL) { + b3AlignedObjectArray bytesReceived; + int clientPort = socket.GetClientPort(); printf("connected from %s:%d\n", socket.GetClientAddr(),clientPort); + //---------------------------------------------------------------------- // Receive request from the client. //---------------------------------------------------------------------- @@ -96,9 +101,27 @@ int main(int argc, char *argv[]) int maxLen = 4 + sizeof(SharedMemoryStatus)+SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE; + + //heuristic to detect disconnected clients + CSimpleSocket::CSocketError err = pClient->GetSocketError(); + if (err != CSimpleSocket::SocketSuccess) + { + b3Clock::usleep(100); + + curNumErr++; + + if (curNumErr>100) + { + printf("TCP Connection error = %d, curNumErr = %d\n", (int)err, curNumErr); + + break; + } + } + if (pClient->Receive(maxLen)) { - + + curNumErr = 0; char* msg2 = (char*) pClient->GetData(); int numBytesRec2 = pClient->GetBytesReceived(); @@ -221,9 +244,8 @@ int main(int argc, char *argv[]) } if (!receivedData) { - printf("Didn't receive data.\n"); - break; - } + //printf("Didn't receive data.\n"); + } } printf("Disconnecting client.\n"); pClient->Close(); diff --git a/examples/ThirdPartyLibs/clsocket/src/SimpleSocket.h b/examples/ThirdPartyLibs/clsocket/src/SimpleSocket.h index 603f46715..2fe555e79 100644 --- a/examples/ThirdPartyLibs/clsocket/src/SimpleSocket.h +++ b/examples/ThirdPartyLibs/clsocket/src/SimpleSocket.h @@ -413,6 +413,14 @@ public: CSocketError GetSocketError(void) { return m_socketErrno; }; + /* + CSocketError GetSocketError(void) { + CSocketError err = m_socketErrno; + m_socketErrno = SocketSuccess; + return err; + + }; + */ /// Get the total time the of the last operation in milliseconds. /// @return number of milliseconds of last operation. diff --git a/examples/pybullet/CMakeLists.txt b/examples/pybullet/CMakeLists.txt index e2d302370..6405903a5 100644 --- a/examples/pybullet/CMakeLists.txt +++ b/examples/pybullet/CMakeLists.txt @@ -95,7 +95,7 @@ ENDIF(WIN32) IF(BUILD_PYBULLET_ENET) - ADD_LIBRARY(pybullet SHARED ${pybullet_SRCS} + set(pybullet_SRCS ${pybullet_SRCS} ../../examples/SharedMemory/PhysicsClientUDP.cpp ../../examples/SharedMemory/PhysicsClientUDP_C_API.cpp ../../examples/SharedMemory/PhysicsClientUDP.h @@ -110,10 +110,11 @@ IF(BUILD_PYBULLET_ENET) ../../examples/ThirdPartyLibs/enet/peer.c ../../examples/ThirdPartyLibs/enet/protocol.c ) -ELSE(BUILD_PYBULLET_ENET) - ADD_LIBRARY(pybullet SHARED ${pybullet_SRCS}) ENDIF(BUILD_PYBULLET_ENET) + +ADD_LIBRARY(pybullet SHARED ${pybullet_SRCS}) + SET_TARGET_PROPERTIES(pybullet PROPERTIES PREFIX "") SET_TARGET_PROPERTIES(pybullet PROPERTIES POSTFIX "") diff --git a/examples/pybullet/pybullet.c b/examples/pybullet/pybullet.c index a33b3afda..179f052a0 100644 --- a/examples/pybullet/pybullet.c +++ b/examples/pybullet/pybullet.c @@ -5,6 +5,10 @@ #include "../SharedMemory/PhysicsClientUDP_C_API.h" #endif //BT_ENABLE_ENET +#ifdef BT_ENABLE_CLSOCKET +#include "../SharedMemory/PhysicsClientTCP_C_API.h" +#endif //BT_ENABLE_CLSOCKET + #ifdef __APPLE__ #include #else @@ -25,6 +29,7 @@ enum eCONNECT_METHOD { eCONNECT_DIRECT = 2, eCONNECT_SHARED_MEMORY = 3, eCONNECT_UDP = 4, + eCONNECT_TCP = 5, }; static PyObject* SpamError; @@ -227,7 +232,9 @@ static PyObject* pybullet_connectPhysicsServer(PyObject* self, PyObject* args, P { int key = SHARED_MEMORY_KEY; - int port = 1234; + int udpPort = 1234; + int tcpPort = 6667; + const char* hostName = "localhost"; int size = PySequence_Size(args); @@ -236,7 +243,7 @@ static PyObject* pybullet_connectPhysicsServer(PyObject* self, PyObject* args, P if (!PyArg_ParseTuple(args, "i", &method)) { PyErr_SetString(SpamError, "connectPhysicsServer expected argument GUI, " - "DIRECT, SHARED_MEMORY or UDP"); + "DIRECT, SHARED_MEMORY, UDP or TCP"); return NULL; } } @@ -250,7 +257,7 @@ static PyObject* pybullet_connectPhysicsServer(PyObject* self, PyObject* args, P if (sPhysicsClientsGUI[i] ==eCONNECT_GUI) { PyErr_SetString(SpamError, - "Only one local in-process GUI connection allowed. Use DIRECT connection mode or start a separate GUI physics server (ExampleBrowser, App_SharedMemoryPhysics_GUI, App_SharedMemoryPhysics_VR) and connect over SHARED_MEMORY or UDP instead."); + "Only one local in-process GUI connection allowed. Use DIRECT connection mode or start a separate GUI physics server (ExampleBrowser, App_SharedMemoryPhysics_GUI, App_SharedMemoryPhysics_VR) and connect over SHARED_MEMORY, UDP or TCP instead."); return NULL; } } @@ -275,12 +282,18 @@ static PyObject* pybullet_connectPhysicsServer(PyObject* self, PyObject* args, P if (size == 3) { + int port = -1; if (!PyArg_ParseTuple(args, "isi", &method, &hostName, &port)) { PyErr_SetString(SpamError, "connectPhysicsServer 3 arguments: method, hostname, port"); return NULL; } + if (port>=0) + { + udpPort = port; + tcpPort = port; + } } @@ -308,7 +321,7 @@ static PyObject* pybullet_connectPhysicsServer(PyObject* self, PyObject* args, P { #ifdef BT_ENABLE_ENET - sm = b3ConnectPhysicsUDP(hostName, port); + sm = b3ConnectPhysicsUDP(hostName, udpPort); #else PyErr_SetString(SpamError, "UDP is not enabled in this pybullet build"); return NULL; @@ -316,6 +329,20 @@ static PyObject* pybullet_connectPhysicsServer(PyObject* self, PyObject* args, P break; } + case eCONNECT_TCP: + { +#ifdef BT_ENABLE_CLSOCKET + + sm = b3ConnectPhysicsTCP(hostName, tcpPort); +#else + PyErr_SetString(SpamError, "TCP is not enabled in this pybullet build"); + return NULL; +#endif //BT_ENABLE_CLSOCKET + + break; + } + + default: { PyErr_SetString(SpamError, "connectPhysicsServer unexpected argument"); @@ -5126,6 +5153,7 @@ initpybullet(void) PyModule_AddIntConstant(m, "DIRECT", eCONNECT_DIRECT); // user read PyModule_AddIntConstant(m, "GUI", eCONNECT_GUI); // user read PyModule_AddIntConstant(m, "UDP", eCONNECT_UDP); // user read + PyModule_AddIntConstant(m, "TCP", eCONNECT_TCP); // user read PyModule_AddIntConstant(m, "JOINT_REVOLUTE", eRevoluteType); // user read PyModule_AddIntConstant(m, "JOINT_PRISMATIC", ePrismaticType); // user read From 5c74b0a1997bcfc1209275ad50ebee66e43d8fb4 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 20 Feb 2017 20:55:37 -0800 Subject: [PATCH 12/12] add cmake support for TCP / clsocket in pybullet --- CMakeLists.txt | 1 + examples/pybullet/CMakeLists.txt | 29 ++++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 66f887175..d3fb18d3c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -218,6 +218,7 @@ IF(BUILD_PYBULLET) OPTION(BUILD_PYBULLET_NUMPY "Set when you want to build pybullet with NumPy support" OFF) OPTION(BUILD_PYBULLET_ENET "Set when you want to build pybullet with enet UDP networking support" ON) + OPTION(BUILD_PYBULLET_CLSOCKET "Set when you want to build pybullet with enet TCP networking support" ON) IF(BUILD_PYBULLET_NUMPY) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_LIST_DIR}/build3/cmake) diff --git a/examples/pybullet/CMakeLists.txt b/examples/pybullet/CMakeLists.txt index 6405903a5..41e0a6c07 100644 --- a/examples/pybullet/CMakeLists.txt +++ b/examples/pybullet/CMakeLists.txt @@ -4,6 +4,7 @@ INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/examples ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/enet/include + ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/clsocket/src ${PYTHON_INCLUDE_DIRS} ) IF(BUILD_PYBULLET_NUMPY) @@ -79,6 +80,9 @@ SET(pybullet_SRCS ../../examples/MultiThreading/b3ThreadSupportInterface.cpp ) +IF(BUILD_PYBULLET_CLSOCKET) + ADD_DEFINITIONS(-DBT_ENABLE_CLSOCKET) +ENDIF(BUILD_PYBULLET_CLSOCKET) IF(WIN32) LINK_LIBRARIES( @@ -87,10 +91,22 @@ IF(WIN32) IF(BUILD_PYBULLET_ENET) ADD_DEFINITIONS(-DWIN32 -DBT_ENABLE_ENET) ENDIF(BUILD_PYBULLET_ENET) + IF(BUILD_PYBULLET_CLSOCKET) + ADD_DEFINITIONS(-DWIN32) + ENDIF(BUILD_PYBULLET_CLSOCKET) + ELSE(WIN32) IF(BUILD_PYBULLET_ENET) ADD_DEFINITIONS(-DHAS_SOCKLEN_T -DBT_ENABLE_ENET) ENDIF(BUILD_PYBULLET_ENET) + + IF(BUILD_PYBULLET_CLSOCKET) + IF(APPLE) + ADD_DEFINITIONS(-D_DARWIN) + ELSE() + ADD_DEFINITIONS(-D_LINUX) + ENDIF() + ENDIF(BUILD_PYBULLET_CLSOCKET) ENDIF(WIN32) @@ -112,6 +128,17 @@ IF(BUILD_PYBULLET_ENET) ) ENDIF(BUILD_PYBULLET_ENET) +IF(BUILD_PYBULLET_CLSOCKET) + set(pybullet_SRCS ${pybullet_SRCS} + ../../examples/SharedMemory/PhysicsClientTCP.cpp + ../../examples/SharedMemory/PhysicsClientTCP.h + ../../examples/SharedMemory/PhysicsClientTCP_C_API.cpp + ../../examples/SharedMemory/PhysicsClientTCP_C_API.h + ../../examples/ThirdPartyLibs/clsocket/src/SimpleSocket.cpp + ../../examples/ThirdPartyLibs/clsocket/src/ActiveSocket.cpp + ../../examples/ThirdPartyLibs/clsocket/src/PassiveSocket.cpp + ) +ENDIF() ADD_LIBRARY(pybullet SHARED ${pybullet_SRCS}) @@ -124,7 +151,7 @@ SET_TARGET_PROPERTIES(pybullet PROPERTIES DEBUG_POSTFIX "_d") IF(WIN32) - IF(BUILD_PYBULLET_ENET) + IF(BUILD_PYBULLET_ENET OR BUILD_PYBULLET_CLSOCKET) TARGET_LINK_LIBRARIES(pybullet ws2_32 ) ENDIF(BUILD_PYBULLET_ENET)