Skip to content

Instantly share code, notes, and snippets.

@zwetan
Created March 18, 2016 09:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zwetan/565109f1138cac00795e to your computer and use it in GitHub Desktop.
Save zwetan/565109f1138cac00795e to your computer and use it in GitHub Desktop.
package flash.net
{
import C.arpa.inet.*;
import C.errno.*;
import C.netdb.*;
import C.netinet.*;
import C.sys.socket.*;
import C.unistd.*;
import flash.utils.ByteArray;
public class Socket
{
private var _connected:Boolean;
private var _sockfd:int;
private var _info:addrinfo;
private var _addrlist:Array;
private var _errors:Array;
private var _localAddress:String;
private var _localPort:int;
private var _remoteAddress:String;
private var _remotePort:int;
private var _remoteAddresses:Array;
/**
* Function hook for the "connect" event.
*/
public var onConnect:Function;/* = function():void
{
trace( "onConnect()" );
}*/
/**
* Function hook for the "disconnect" event.
*/
public var onDisconnect:Function;/* = function():void
{
trace( "onDisconnect()" );
}*/
public function Socket( host:String = null, port:int = 0 )
{
super();
_reset();
if( host != null )
{
this.connect( host, port );
}
}
private function _reset():void
{
_connected = false;
_sockfd = -1;
_info = null;
_addrlist = null;
_errors = [];
_localAddress = "";
_localPort = -1;
_remoteAddress = "";
_remotePort = -1;
_remoteAddresses = null;
}
private function _findLocalAddressAndPort():void
{
if( _info.ai_family == AF_INET )
{
_findLocalAddressAndPort4();
}
else
{
_findLocalAddressAndPort6();
}
}
private function _findLocalAddressAndPort4():void
{
var addr:sockaddr_in = new sockaddr_in();
var result:int = getsockname( _sockfd, addr );
if( result == -1 )
{
var e:CError = new CError( "", errno );
_errors.push( e );
}
else
{
var a:String = inet_ntop( addr.sin_family, addr );
if( !a )
{
var e:CError = new CError( "", errno );
_errors.push( e );
return;
}
else
{
_localAddress = a;
}
_localPort = ntohs( addr.sin_port );
}
}
private function _findLocalAddressAndPort6():void
{
var addr:sockaddr_in6 = new sockaddr_in6();
var result:int = getsockname( _sockfd, addr );
if( result == -1 )
{
var e:CError = new CError( "", errno );
_errors.push( e );
}
else
{
var a:String = inet_ntop( addr.sin6_family, addr );
if( !a )
{
var e:CError = new CError( "", errno );
_errors.push( e );
return;
}
else
{
_localAddress = a;
}
_localPort = ntohs( addr.sin6_port );
}
}
private function _listRemoteAddresses():Array
{
var addresses:Array = [];
if( !_addrlist ) { return addresses; }
var i:uint;
var info:addrinfo;
for( i = 0; i < _addrlist.length; i++ )
{
info = _addrlist[i];
addresses.push( inet_ntop( info.ai_family, info.ai_addr ) );
}
return addresses;
}
//private native function internalConnect(host:String, port:int):void;
private function _internalConnect( host:String, port:int ):void
{
var hostname:String = host;
var hostport:String = String( port );
var hints:addrinfo = new addrinfo();
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_UNSPEC;
var eaierr:CEAIrror = new CEAIrror();
var addrlist:Array = getaddrinfo( hostname, hostport, hints, eaierr );
if( !addrlist )
{
_errors.push( eaierr );
return;
}
_addrlist = addrlist;
var i:uint;
var info:addrinfo;
var sockfd:int;
var result:int;
for( i = 0; i < addrlist.length; i++ )
{
info = addrlist[i];
sockfd = C.sys.socket.socket( info.ai_family, info.ai_socktype, info.ai_protocol );
if( sockfd < 0 )
{
var e:CError = new CError( "", errno );
_errors.push( e );
return;
}
result = C.sys.socket.connect( sockfd, info.ai_addr );
if( result < 0 )
{
var e:CError = new CError( "", errno );
_errors.push( e );
return;
}
break;
}
_info = info;
var a:String = inet_ntop( _info.ai_family, _info.ai_addr );
if( !a )
{
var e:CError = new CError( "", errno );
_errors.push( e );
}
else
{
_remoteAddress = a;
}
if( _info.ai_family == AF_INET )
{
// IPv4
_remotePort = ntohs( _info.ai_addr.sin_port );
}
else
{
// IPv6
_remotePort = ntohs( _info.ai_addr.sin6_port );
}
_sockfd = sockfd;
}
public function connect( host:String, port:int ):void
{
trace( "connect: host="+host+", port="+port );
_internalConnect( host, port );
if( _sockfd == -1 )
{
trace( "Could not connect to " + host + ":" + port );
return;
}
else
{
_connected = true;
_findLocalAddressAndPort();
if( onConnect ) { this.onConnect(); }
}
}
//private native function internalClose():void;
private function _internalClose():void
{
if( !_connected )
{
/* NOTE
never connected
or already disconnected
*/
return;
}
var result:int = C.unistd.close( _sockfd );
if( result == -1 )
{
var e:CError = new CError( "", errno );
_errors.push( e );
return;
}
if( onDisconnect ) { this.onDisconnect(); }
_reset();
}
public function close():void
{
_internalClose();
}
public function toDebugString():String
{
//trace( "HttpConnection.toString()" );
var str:String = "";
str += "{Socket";
if( _connected )
{
str += " connected:";
str += " " + _localAddress;
str += ":" + _localPort;
str += " =>";
str += " " + _remoteAddress;
str += ":" + _remotePort;
}
else
{
str += " disconnected";
}
str += " ";
str += "}";
return str;
}
}
}
@zwetan
Copy link
Author

zwetan commented Mar 18, 2016

build with redbean

project structure

├── build.as3
├── flash_net.abc
├── src
│   ├── flash
│   │   └── net
│   │       └── Socket.as
│   └── flash_net.as
└── test_flashnet

define include list
flash_net.as

include "flash/net/Socket.as"

"flahs_net 0.1";

build.as3

import redbean.*;
import shell.FileSystem;


compile( "src/flash_net.as" );

if( FileSystem.exists( "flash_net.abc" ) )
{
    FileSystem.removeFile( "flash_net.abc" );
}

FileSystem.move( "src/flash_net.abc", "flash_net.abc" );

test with as3shebang

test_flashnet

#!/usr/bin/as3shebang

import shell.*;

var flash_net:* = Domain.currentDomain.load( "flash_net.abc" );
trace( flash_net + " loaded" );

import flash.net.Socket;

var s:* = new Socket();
    s.onConnect = function()
    {
        trace( "onConnect()" );
        trace( s.toDebugString() );
    }
    s.onDisconnect = function()
    {
        trace( "onDisconnect()" );
        trace( s.toDebugString() );
    }


trace( s );
s.connect( "www.google.com", 80 );
s.close();

@zwetan
Copy link
Author

zwetan commented Mar 18, 2016

Usage

build the lib
$ redbean

test the list
$ ./test_flashnet

output should be

flahs_net 0.1 loaded
[object Socket]
connect: host=www.google.com, port=80
onConnect()
{Socket connected: 192.168.0.64:52438 => 216.58.211.100:80 }
onDisconnect()
{Socket connected: 192.168.0.64:52438 => 216.58.211.100:80 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment