PageRenderTime 55ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/jabber/SocketConnection.hx

http://github.com/outbounder/org.abn.haxe
Haxe | 408 lines | 273 code | 59 blank | 76 comment | 32 complexity | 1efbd70c6e273ba5ded97189018dba87 MD5 | raw file
Possible License(s): LGPL-3.0
  1. /*
  2. * This file is part of HXMPP.
  3. * Copyright (c)2009 http://www.disktree.net
  4. *
  5. * HXMPP is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Lesser General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * HXMPP is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. * See the GNU Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public License
  16. * along with HXMPP. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. package jabber;
  19. #if flash9
  20. import flash.net.Socket;
  21. import flash.events.Event;
  22. import flash.events.IOErrorEvent;
  23. import flash.events.SecurityErrorEvent;
  24. import flash.events.ProgressEvent;
  25. import flash.utils.ByteArray;
  26. #elseif neko
  27. import neko.net.Host;
  28. import neko.net.Socket;
  29. #elseif php
  30. import php.net.Host;
  31. import net.php.Socket;
  32. #elseif cpp
  33. import cpp.net.Host;
  34. import cpp.net.Socket;
  35. #end
  36. /**
  37. TODO
  38. - php!
  39. - flash/js maxBufSize
  40. - split outgoing (big) packets ?
  41. */
  42. class SocketConnection extends jabber.stream.Connection {
  43. #if (neko||php||cpp)
  44. public static var defaultBufSize = (1<<8); // 128
  45. #end
  46. public var port(default,null) : Int;
  47. public var socket(default,null) : Socket;
  48. public var secure(default,null) : Bool; //TODO move to jabber.socket.Connection
  49. public var timeout(default,null) : Int;
  50. public var maxBufSize(default,null) : Int;
  51. #if (neko||php||cpp)
  52. var reading : Bool;
  53. var buf : haxe.io.Bytes;
  54. var bufbytes : Int;
  55. #elseif (JABBER_SOCKETBRIDGE)
  56. var buf : String;
  57. #elseif flash
  58. var buf : ByteArray;
  59. #end
  60. public function new( host : String,
  61. ?port : Int,
  62. ?secure : Bool = false ,
  63. ?timeout : Int = 10,
  64. ?maxBufSize : Int = 131072 ) {
  65. if( port == null )
  66. port = 5222;
  67. super( host );
  68. this.port = port;
  69. #if (flash10||neko||php||cpp)
  70. this.timeout = timeout;
  71. #end
  72. this.secure = secure;
  73. this.maxBufSize = maxBufSize;
  74. socket = new Socket();
  75. #if flash9
  76. buf = new ByteArray();
  77. socket.addEventListener( Event.CONNECT, sockConnectHandler );
  78. socket.addEventListener( Event.CLOSE, sockDisconnectHandler );
  79. socket.addEventListener( IOErrorEvent.IO_ERROR, sockErrorHandler );
  80. socket.addEventListener( SecurityErrorEvent.SECURITY_ERROR, sockErrorHandler );
  81. #elseif (neko||cpp)
  82. socket = new Socket();
  83. buf = haxe.io.Bytes.alloc( defaultBufSize );
  84. bufbytes = 0;
  85. reading = false;
  86. #elseif php
  87. buf = haxe.io.Bytes.alloc( maxBufSize ); //TODO ! WTF !!!
  88. bufbytes = 0;
  89. reading = false;
  90. #elseif JABBER_SOCKETBRIDGE
  91. buf = "";
  92. socket.onConnect = sockConnectHandler;
  93. socket.onDisconnect = sockDisconnectHandler;
  94. socket.onError = sockErrorHandler;
  95. #end
  96. }
  97. /*
  98. function setTimeout( t : Int ) : Int {
  99. return timeout = ( t <= 0 ) ? 1 : t;
  100. }
  101. function setMaxBufSize( t : Int ) : Int {
  102. return timeout = ( t <= 0 ) ? 1 : t;
  103. }
  104. */
  105. public override function connect() {
  106. #if (neko||cpp)
  107. socket.connect( new Host( host ), port );
  108. #end
  109. #if php
  110. if( secure ) socket.connectTLS( new Host( host ), port )
  111. else socket.connect( new Host( host ), port );
  112. #end
  113. #if (neko||php||cpp)
  114. connected = true;
  115. __onConnect();
  116. #else
  117. #if flash10
  118. socket.timeout = timeout*1000;
  119. #end
  120. socket.connect( host, port );
  121. #end
  122. }
  123. public override function disconnect() {
  124. if( !connected ) return;
  125. #if (neko||php||cpp) reading = false; #end
  126. connected = #if (neko||php||cpp) reading = #end false;
  127. socket.close();
  128. }
  129. public override function read( ?yes : Bool = true ) : Bool {
  130. if( yes ) {
  131. #if flash9
  132. socket.addEventListener( ProgressEvent.SOCKET_DATA, sockDataHandler );
  133. #elseif (neko||php||cpp)
  134. reading = true;
  135. while( reading && connected ) {
  136. readData();
  137. processData();
  138. }
  139. #elseif JABBER_SOCKETBRIDGE
  140. socket.onData = sockDataHandler;
  141. #end
  142. } else {
  143. #if flash9
  144. socket.removeEventListener( ProgressEvent.SOCKET_DATA, sockDataHandler );
  145. #elseif (neko||php||cpp)
  146. reading = false;
  147. #elseif JABBER_SOCKETBRIDGE
  148. socket.onData = null;
  149. #end
  150. }
  151. return true;
  152. }
  153. public override function write( t : String ) : Bool {
  154. if( !connected || t == null || t.length == 0 )
  155. return false;
  156. #if flash9
  157. socket.writeUTFBytes( t );
  158. socket.flush();
  159. #elseif (neko||php||cpp)
  160. socket.output.writeString( t );
  161. socket.output.flush();
  162. #elseif JABBER_SOCKETBRIDGE
  163. socket.send( t );
  164. #end
  165. return true;
  166. }
  167. /*
  168. public function clearBuffer() {
  169. #if (neko||php)
  170. buf = haxe.io.Bytes.alloc( DEFAULT_BUFSIZE );
  171. bufbytes = 0;
  172. #end
  173. }
  174. */
  175. #if (flash)
  176. function sockConnectHandler( e : Event ) {
  177. connected = true;
  178. onConnect();
  179. }
  180. function sockDisconnectHandler( e : Event ) {
  181. connected = false;
  182. onDisconnect();
  183. }
  184. function sockErrorHandler( e ) {
  185. connected = false;
  186. onError( e );
  187. }
  188. function sockDataHandler( e : ProgressEvent ) {
  189. socket.readBytes( buf, buf.length, e.bytesLoaded);
  190. var b = haxe.io.Bytes.ofData( buf );
  191. if( b.length > maxBufSize )
  192. throw "Max buffer size reached ("+maxBufSize+")";
  193. if( onData( b, 0, b.length ) > 0 )
  194. buf = new flash.utils.ByteArray();
  195. }
  196. #elseif (neko||php||cpp)
  197. function readData() {
  198. var buflen = buf.length;
  199. if( bufbytes == buflen ) { // eventually double the buffer size
  200. var nsize = buflen*2;
  201. if( nsize > maxBufSize ) {
  202. if( buflen == maxBufSize )
  203. throw "Max buffer size reached ("+maxBufSize+")";
  204. nsize = maxBufSize;
  205. }
  206. var buf2 = haxe.io.Bytes.alloc( nsize );
  207. buf2.blit( 0, buf, 0, buflen );
  208. buflen = nsize;
  209. buf = buf2;
  210. }
  211. var nbytes = 0;
  212. // try {
  213. //trace(buf.length+"//"+buflen+"//"+bufbytes);
  214. nbytes = socket.input.readBytes( buf, bufbytes, buflen-bufbytes );
  215. //trace(nbytes);
  216. // } catch(e:Dynamic){
  217. // trace("ERRIR "+e);
  218. // throw e;
  219. // }
  220. bufbytes += nbytes;
  221. }
  222. function processData() {
  223. var pos = 0;
  224. while( bufbytes > 0 && reading ) {
  225. var nbytes = __onData( buf, pos, bufbytes ); //var nbytes = handleData( buffer, pos, bufbytes );
  226. if( nbytes == 0 ) {
  227. return;
  228. }
  229. /*
  230. if( nbytes == -1 ) {
  231. reading = false;
  232. disconnect();
  233. return;
  234. }
  235. */
  236. pos += nbytes;
  237. bufbytes -= nbytes;
  238. }
  239. if( reading && pos > 0 )
  240. buf.blit( 0, buf, pos, bufbytes );
  241. }
  242. #elseif JABBER_SOCKETBRIDGE
  243. function sockConnectHandler() {
  244. connected = true;
  245. onConnect();
  246. }
  247. function sockDisconnectHandler() {
  248. connected = false;
  249. onDisconnect();
  250. }
  251. function sockErrorHandler( m : String ) {
  252. connected = false;
  253. onError( m );
  254. }
  255. function sockDataHandler( t : String ) {
  256. var i = buf + t;
  257. if( i.length > maxBufSize ) {
  258. #if JABBER_DEBUG trace( "Max socket buffer size reached ("+maxBufSize+")" ); #end
  259. throw "Max socket buffer size reached ("+maxBufSize+")";
  260. }
  261. buf = ( __onData( haxe.io.Bytes.ofString( i ), 0, i.length ) == 0 ) ? i : "";
  262. }
  263. #end
  264. }
  265. #if JABBER_SOCKETBRIDGE
  266. /**
  267. Socket for socketbridge use.
  268. */
  269. class Socket {
  270. public dynamic function onConnect() : Void;
  271. public dynamic function onDisconnect() : Void;
  272. public dynamic function onData( d : String ) : Void;
  273. public dynamic function onError( e : String ) : Void;
  274. public var id(default,null) : Int;
  275. //var timeout : Int;
  276. public function new() {
  277. var id : Int = SocketBridgeConnection.createSocket( this );
  278. if( id < 0 ) "Error creating socket";
  279. this.id = id;
  280. }
  281. public function connect( host : String, port : Int ) {
  282. untyped js.Lib.document.getElementById( SocketBridgeConnection.bridgeId ).connect( id, host, port );
  283. }
  284. public function close() {
  285. untyped js.Lib.document.getElementById( SocketBridgeConnection.bridgeId ).disconnect( id );
  286. }
  287. /*
  288. public function destroy() {
  289. var _s = untyped js.Lib.document.getElementById( SocketBridgeConnection.bridgeId ).destroy( id );
  290. }
  291. */
  292. public function send( d : String ) {
  293. untyped js.Lib.document.getElementById( SocketBridgeConnection.bridgeId ).send( id, d );
  294. }
  295. }
  296. /**
  297. */
  298. class SocketBridgeConnection {
  299. //public static var defaultBridgeId = "f9bridge";
  300. public static var defaultDelay = 300;
  301. public static var bridgeId(default,null) : String;
  302. static var sockets : IntHash<Socket>;
  303. static var initialized = false;
  304. public static function init( id : String ) {
  305. if( initialized )
  306. throw "Socketbridge already initialized";
  307. bridgeId = id;
  308. sockets = new IntHash();
  309. initialized = true;
  310. }
  311. public static function initDelayed( id : String, cb : Void->Void, ?delay : Int ) {
  312. if( delay == null || delay <= 0 ) delay = defaultDelay;
  313. init( id );
  314. haxe.Timer.delay( cb, delay );
  315. }
  316. public static function createSocket( s : Socket ) {
  317. var id : Int = untyped js.Lib.document.getElementById( bridgeId ).createSocket();
  318. sockets.set( id, s );
  319. return id;
  320. }
  321. /*
  322. public static function destroySocket( id : Int ) {
  323. var removed = untyped js.Lib.document.getElementById( bridgeId ).destroySocket( id );
  324. if( removed ) {
  325. var s = sockets.get( id );
  326. sockets.remove( id );
  327. s = null;
  328. }
  329. }
  330. */
  331. static function handleConnect( id : Int ) {
  332. var s = sockets.get( id );
  333. s.onConnect();
  334. }
  335. static function handleDisonnect( id : Int ) {
  336. var s = sockets.get( id );
  337. s.onDisconnect();
  338. }
  339. static function handleError( id : Int, e : String ) {
  340. var s = sockets.get( id );
  341. s.onError( e );
  342. }
  343. static function handleData( id : Int, d : String ) {
  344. var s = sockets.get( id );
  345. s.onData( d );
  346. }
  347. }
  348. #end // JABBER_SOCKETBRIDGE