#ifdef LINUX
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#endif
#include <maya/MFnPlugin.h>
#include <maya/MTypeId.h>
#include <api_macros.h>
#include <maya/MIOStream.h>
#include <maya/MString.h>
#include <maya/MStringArray.h>
#include <maya/MPlug.h>
#include <maya/MDataBlock.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MPxClientDeviceNode.h>
{
public:
                udpDeviceNode();
    virtual         ~udpDeviceNode();
    
    virtual void        threadHandler( 
const char* serverName, 
const char* deviceName );
 
    static void*        creator();
public:
private:
};
MTypeId udpDeviceNode::id( 0x00081052 );
 
MObject udpDeviceNode::outputTranslate;
 
MObject udpDeviceNode::outputTranslateX;
 
MObject udpDeviceNode::outputTranslateY;
 
MObject udpDeviceNode::outputTranslateZ;
 
udpDeviceNode::udpDeviceNode() 
{}
udpDeviceNode::~udpDeviceNode()
{
    destroyMemoryPools();
}
void udpDeviceNode::postConstructor()
{
    attrArray.
append( udpDeviceNode::outputTranslate );
    setRefreshOutputAttributes( attrArray );
    
    createMemoryPools( 1, 1024, sizeof(char));
}
void udpDeviceNode::threadHandler( const char* serverName, const char* deviceName )
{
    setDone( false );
    if ( serverName != NULL && deviceName != NULL )
        printf("udpThreadHandler: %s %s\n",serverName,deviceName);
#ifdef LINUX
    int sock;
    int bytesRead;
    socklen_t addressLength;
    struct sockaddr_in serverAddress , clientAddress;
    
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons(7555);
    serverAddress.sin_addr.s_addr = INADDR_ANY;
    bzero(&(serverAddress.sin_zero),8);
    addressLength = sizeof(struct sockaddr);
    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 
    {
        return;
    }
    if (bind(sock,(struct sockaddr *)&serverAddress,
        sizeof(struct sockaddr)) == -1)
    {
        return;
    }
    char receiveBuffer[1024];
    while ( !isDone() )
    {
        if ( ! isLive() )
            continue;
        
        
        fd_set read_set;
        FD_ZERO( &read_set );
        FD_SET( sock, &read_set );
        struct timeval tv;
        tv.tv_sec = 0;
        tv.tv_usec = 500000; 
        if ( select( sock+1, &read_set, NULL, NULL, &tv ) == -1 )
            break;
        if ( ! FD_ISSET( sock, &read_set ) )
            continue;
        receiveBuffer[0] = 0;
        bytesRead = recvfrom(sock,receiveBuffer,1024,0,
            (struct sockaddr *)&clientAddress, &addressLength);
            
        const char *receivedFromServer = inet_ntoa(clientAddress.sin_addr);
        unsigned short receivedFromPort = ntohs(clientAddress.sin_port);
        
        if ( NULL == receivedFromServer )
            continue;
        
        printf("(%s , %d) connection : %s \n",receivedFromServer,receivedFromPort, receiveBuffer);
        
        
        if ( 0 != strcmp( serverName, receivedFromServer ) )
            continue;
        
        status = acquireDataStorage(buffer);
        if ( ! status )
            continue;
        beginThreadLoop();
        {
            receiveBuffer[bytesRead] = '\0';
            double* doubleData = 
reinterpret_cast<double*
>(buffer.
ptr());
 
            doubleData[0] = 0.0 ; doubleData[1] = 0.0; doubleData[2] = 0.0;
            if ( s.split( ' ', sa ) )
            {
                {
                    int i = 0;
                    for ( i = 0; i < 3; i++ )
                    {
                        doubleData[i] = ( sa[i].isDouble() ? sa[i].asDouble() : 0.0 );
                    }
                }   
            }
            pushThreadData( buffer );
        }
        endThreadLoop();
    }
    
    
    close( sock );
    
#endif // LINUX
    setDone( true );
}
void udpDeviceNode::threadShutdownHandler()
{
    setDone( true );
}
void* udpDeviceNode::creator()
{
    return new udpDeviceNode;
}
MStatus udpDeviceNode::initialize()
 
{
    MCHECKERROR(status, "create outputTranslateX");
    MCHECKERROR(status, "create outputTranslateY");
    MCHECKERROR(status, "create outputTranslateZ");
    outputTranslate = numAttr.
create(
"outputTranslate", 
"ot", outputTranslateX, outputTranslateY, 
                                     outputTranslateZ, &status);
    MCHECKERROR(status, "create outputTranslate");
    
    ADD_ATTRIBUTE(outputTranslate);
    ATTRIBUTE_AFFECTS( live, outputTranslate);
    ATTRIBUTE_AFFECTS( frameRate, outputTranslate);
    ATTRIBUTE_AFFECTS( serverName, outputTranslate);
    ATTRIBUTE_AFFECTS( deviceName, outputTranslate);
}
{
    if( plug == outputTranslate || plug == outputTranslateX ||
        plug == outputTranslateY || plug == outputTranslateZ )
    {
        if ( popThreadData(buffer) )
        {
            double* doubleData = 
reinterpret_cast<double*
>(buffer.
ptr());
 
            MCHECKERROR(status, "Error in block.outputValue for outputTranslate");
            double3& outputTranslate = outputTranslateHandle.
asDouble3();
            outputTranslate[0] = doubleData[0];
            outputTranslate[1] = doubleData[1];
            outputTranslate[2] = doubleData[2];
            releaseDataStorage(buffer);
        }
        else
        {
        }
    }
}
{
    MFnPlugin plugin(obj, PLUGIN_COMPANY, 
"3.0", 
"Any");
 
    status = plugin.registerNode( "udpDevice", 
                                  udpDeviceNode::id,
                                  udpDeviceNode::creator,
                                  udpDeviceNode::initialize,
    if( !status ) {
        status.
perror(
"failed to registerNode udpDeviceNode");
    }
    return status;
}
{
    status = plugin.deregisterNode( udpDeviceNode::id );
    if( !status ) {
        status.
perror(
"failed to deregisterNode udpDeviceNode");
    }
    return status;
}