/*
Milenia Grafter Server
Copyright (c) 2007-2008 by Milan Toth. All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.milgra.server.encoder;
/**
RtmpHsa class
@mail milgra@milgra.com
@author Milan Toth
@version 20080316
Tasks of RtmpHsa
- Realize an rtmp handshake on the host side
**/
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.channels.NotYetConnectedException;
import com.milgra.server.Library;
import com.milgra.server.OProcess;
import com.milgra.server.SocketController;
public class RtmpHsa extends OProcess
{
// state - handshake state
public int state = 0;
public ByteBuffer stampBuffer;
public ByteBuffer replyBuffer;
public ByteBuffer firstBuffer;
public SocketChannel socket;
public SocketController controller;
/**
* Creates a RtmpHsa instance
* @param controllerX SocketController
* @param socketX SocketChanne;
*/
public RtmpHsa ( SocketController controllerX )
{
// System.out.println( System.currentTimeMillis( ) + " " + controllerX.id + " RtmpHsa.construct" );
stampBuffer = ByteBuffer.allocate( 1537 );
replyBuffer = ByteBuffer.allocate( 3073 );
firstBuffer = ByteBuffer.allocate( 1536 );
controller = controllerX;
// active handshake starts with 0x03
stampBuffer.put( ( byte ) 0x03 );
for ( int index = 0 ; index < 1536 ; index++ )
{
String hex = Library.HSHASH.substring( index * 2 , index * 2 + 2 );
int hexa = Integer.parseInt( hex , 16 );
stampBuffer.put( ( byte ) hexa );
}
stampBuffer.rewind( );
}
/**
* Closes handshaker
*/
public void close ( )
{
// System.out.println( System.currentTimeMillis( ) + " " + controllerX.id + " RtmpHsa.construct" );
stampBuffer = null;
replyBuffer = null;
firstBuffer = null;
controller = null;
}
/**
* Steps one in handshake.
*/
public void step ( )
{
//System.out.println( System.currentTimeMillis( ) + " " + controller.id + " RtmpHsa.step" );
try
{
if ( state == 0 ) sendStamp( );
if ( state == 1 ) receiveAnswer( );
if ( state == 2 ) sendConnection( );
}
catch ( IOException exception ) { controller.close( "Connection closed." ); }
}
/**
* Sends first handshake chunk - 0x03 followed by 1536 bytes of random data, in this case zeros
* @throws IOException
*/
public void sendStamp ( ) throws IOException
{
// System.out.println( System.currentTimeMillis( ) + " " + controller.id + " RtmpHsa.sendStamp " + 1537 );
try
{
// trying to write stamp buffer
// if all is written, step to next phase
socket.write( stampBuffer );
if ( !stampBuffer.hasRemaining( ) ) state = 1;
}
catch ( NotYetConnectedException exception ) { exception.printStackTrace( ); }
catch ( IOException exception ) { throw exception; }
}
/**
* Receives server's answer, 0x03 followed by 1536 bytes from previous step followed by 1536 random bytes from server
* @throws IOException
*/
public void receiveAnswer ( ) throws IOException
{
// System.out.println( System.currentTimeMillis( ) + " " + controller.id + " RtmpHsa.receiveAnswer " );
try
{
// trying to read reply
// if eof happened, close
// if all is read, step to next phase
int bytes = socket.read( replyBuffer );
if ( bytes == -1 ) throw new IOException( "Disconnected at handshake" );
if ( !replyBuffer.hasRemaining( ) )
{
// positioning reply to client's stamp
replyBuffer.position( 1 );
byte [ ] temp = new byte[1536];
replyBuffer.get( temp );
firstBuffer.put( temp );
firstBuffer.rewind( );
state = 2;
}
}
catch ( IOException exception ) { throw exception; }
}
/**
* Last step, send back second 1536 bytes, then tells ClientController to send connection invoke
* @throws IOException
*/
public void sendConnection ( ) throws IOException
{
// System.out.println( System.currentTimeMillis( ) + " " + controller.id + " RtmpHsa.sendConnection " + 1536 );
try
{
// trying to write first packet's first part
// if success, start rtmp communication
socket.write( firstBuffer );
if ( !firstBuffer.hasRemaining( ) ) controller.startCommunication( );
}
catch ( IOException exception ) { throw exception; }
}
}