782 lines · 22.1 KB · C++
RawDownload
/*----------------------------------------------------------------------------  ChucK Concurrent, On-the-fly Audio Programming Language    Compiler and Virtual Machine   Copyright (c) 2004 Ge Wang and Perry R. Cook.  All rights reserved.    http://chuck.stanford.edu/    http://chuck.cs.princeton.edu/   This program is free software; you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation; either version 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307  U.S.A.-----------------------------------------------------------------------------*/ //-----------------------------------------------------------------------------// file: chuck_otf.cpp// desc: on-the-fly programming utilities//// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)// date: Autumn 2004//-----------------------------------------------------------------------------#include "chuck_otf.h"#include "chuck_compile.h"#include "chuck_errmsg.h"#include "util_math.h"#include "util_thread.h"#include "util_string.h"#include "util_platforms.h" #include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <signal.h>#include <time.h> #ifndef __PLATFORM_WIN32__#include <unistd.h>#else // 2022 QTSIN#include <winsock2.h>#include <ws2tcpip.h>#include <windows.h>#endif using namespace std; // log levelt_CKUINT g_otf_log = CK_LOG_INFO;    //-----------------------------------------------------------------------------// name: otf_hton( )// desc: ...//-----------------------------------------------------------------------------void otf_hton( Net_Msg * msg ){    msg->header = htonl( msg->header );    msg->type = htonl( msg->type );    msg->param = htonl( msg->param );    msg->param2 = htonl( msg->param2 );    msg->param3 = htonl( msg->param3 );    msg->length = htonl( msg->length );}    //-----------------------------------------------------------------------------// name: otf_ntoh( )// desc: ...//-----------------------------------------------------------------------------void otf_ntoh( Net_Msg * msg ){    msg->header = ntohl( msg->header );    msg->type = ntohl( msg->type );    msg->param = ntohl( msg->param );    msg->param2 = ntohl( msg->param2 );    msg->param3 = ntohl( msg->param3 );    msg->length = ntohl( msg->length );}    //-----------------------------------------------------------------------------// name: recv_file()// desc: ...//-----------------------------------------------------------------------------FILE * recv_file( const Net_Msg & msg, ck_socket sock ){    Net_Msg buf;     // what is left    // t_CKUINT left = msg.param2;     // make a temp file    FILE * fd = ck_tmpfile();    // check if successful    if( !fd )    {        EM_error2( 0, "OTF nable to create temp file, skipping..." );        return NULL;    }     do {        // msg        if( !ck_recv( sock, (char *)&buf, sizeof(buf) ) )            goto error;        otf_ntoh( &buf );        // write        fwrite( buf.buffer, sizeof(char), buf.length, fd );    }while( buf.param2 > 0 );     // check for error    if( buf.param2 == NET_ERROR )    {        // this was a problem        EM_log( CK_LOG_INFO, "(via otf): received error flag, dropping..." );        // done        goto error;    }     return fd; error:    fclose( fd );    fd = NULL;    return NULL;}    //-----------------------------------------------------------------------------// name: otf_process_msg()// desc: ...//-----------------------------------------------------------------------------t_CKUINT otf_process_msg( Chuck_VM * vm, Chuck_Compiler * compiler,                          Net_Msg * msg, t_CKBOOL immediate, void * data ){    Chuck_Msg * cmd = new Chuck_Msg;    Chuck_VM_Code * code = NULL;    FILE * fd = NULL;    t_CKUINT ret = 0;     // CK_FPRINTF_STDERR( "UDP message recv...\n" );    if( msg->type == MSG_REPLACE || msg->type == MSG_ADD )    {        string filename;        vector<string> args;         // parse out command line arguments        if( !extract_args( msg->buffer, filename, args ) )        {            // error            CK_FPRINTF_STDERR( "[chuck]: malformed filename with argument list...\n" );            CK_FPRINTF_STDERR( "    -->  '%s'", msg->buffer );            SAFE_DELETE(cmd);            goto cleanup;        }         // copy de-escaped filename        strcpy( msg->buffer, filename.c_str() );        // copy args if needed        if( args.size() > 0 )        {            cmd->args = new vector<string>;            *(cmd->args) = args;        }         // see if entire file is on the way        if( msg->param2 && msg->param2 != NET_ERROR )        {            fd = recv_file( *msg, (ck_socket)data );            if( !fd )            {                CK_FPRINTF_STDERR( "[chuck]: incoming source transfer '%s' failed...\n",                    mini(msg->buffer) );                SAFE_DELETE(cmd);                goto cleanup;            }        }         // construct full path to be associated with the file so me.sourceDir() works        // (added 1.3.5.2)        std::string full_path = get_full_path( msg->buffer );        // special FILE descriptor mode; set autoClose to true        compiler->set_file2parse( fd, TRUE );        // parse, type-check, and emit        if( !compiler->go( msg->buffer, full_path ) )        {            SAFE_DELETE(cmd);            goto cleanup;        }         // get the code        code = compiler->output();        // name it        code->name += string(msg->buffer);         // set the flags for the command        cmd->type = msg->type;        cmd->code = code;        if( msg->type == MSG_REPLACE )            cmd->param = msg->param;    }    else if( msg->type == MSG_STATUS || msg->type == MSG_REMOVE || msg->type == MSG_REMOVEALL             || msg->type == MSG_EXIT || msg->type == MSG_TIME || msg->type == MSG_RESET_ID             || msg->type == MSG_CLEARVM )    {        cmd->type = msg->type;        cmd->param = msg->param;    }    else if( msg->type == MSG_ABORT )    {        // halt and clear current shred        vm->abort_current_shred();        // short circuit        ret = 1;        SAFE_DELETE(cmd);        goto cleanup;    }    else    {        CK_FPRINTF_STDERR( "[chuck]: unrecognized incoming command from network: '%li'\n", cmd->type );        SAFE_DELETE(cmd);        goto cleanup;    }     // immediate    if( immediate )        ret = vm->process_msg( cmd );    else    {        // queue message        vm->queue_msg( cmd, 1 );        // return code        ret = 1;    } cleanup:    // close file handle    if( fd ) fclose( fd );     return ret;}    //-----------------------------------------------------------------------------// name: otf_send_file()// desc: ...//-----------------------------------------------------------------------------t_CKINT otf_send_file( const char * fname, Net_Msg & msg, const char * op,                       ck_socket dest ){    FILE * fd = NULL;    struct stat fs;    string filename;    vector<string> args;    string buf;     // parse out command line arguments    if( !extract_args( fname, filename, args ) )    {        // error        CK_FPRINTF_STDERR( "[chuck]: malformed filename + argument list...\n" );        CK_FPRINTF_STDERR( "    -->  '%s'", fname );        return FALSE;    }     // filename and any args    strcpy( msg.buffer, fname );     // test it    buf = filename;    fd = ck_openFileAutoExt( buf, ".ck" );    if( !fd )    {        CK_FPRINTF_STDERR( "[chuck]: cannot open file '%s' for [%s]...\n", filename.c_str(), op );        return FALSE;    }     if( !chuck_parse( filename ) )    {        CK_FPRINTF_STDERR( "[chuck]: skipping file '%s' for [%s]...\n", filename.c_str(), op );        fclose( fd );        return FALSE;    }     // stat it    memset( &fs, 0, sizeof(fs) );    stat( buf.c_str(), &fs );    fseek( fd, 0, SEEK_SET );     // log    EM_log( CK_LOG_INFO, "sending TCP file %s, size=%d", filename.c_str(), (t_CKUINT)fs.st_size );    EM_pushlog();     // send the first packet    msg.param2 = (t_CKUINT)fs.st_size;    msg.length = 0;    otf_hton( &msg );    // go    ck_send( dest, (char *)&msg, sizeof(msg) );     // send the whole thing    t_CKUINT left = (t_CKUINT)fs.st_size;    while( left )    {        // log        EM_log( CK_LOG_FINER, "%03d bytes left ... ", left );        // amount to send        msg.length = left > NET_BUFFER_SIZE ? NET_BUFFER_SIZE : left;        // read        msg.param3 = fread( msg.buffer, sizeof(char), msg.length, fd );        // check for error        if( !msg.param3 )        {            // error encountered            CK_FPRINTF_STDERR( "[chuck]: error while reading '%s'...\n", filename.c_str() );            // mark done            left = 0;            // error flag            msg.param2 = NET_ERROR;        }        else        {            // amount left            left -= msg.param3;            // what's left            msg.param2 = left;        }         // log        EM_log( CK_LOG_FINER, "sending buffer %03d length %03d...", msg.param3, msg.length );        // send it        otf_hton( &msg );        ck_send( dest, (char *)&msg, sizeof(msg) );    }     // pop log    EM_poplog();     // close    fclose( fd );     return TRUE;}    //-----------------------------------------------------------------------------// name: otf_send_connect()// desc: ...//-----------------------------------------------------------------------------ck_socket otf_send_connect( const char * host, t_CKINT port ){    // log    EM_log( CK_LOG_INFO, "otf connect: %s:%i", host, port );     ck_socket sock = ck_tcp_create( 0 );    if( !sock )    {        CK_FPRINTF_STDERR( "[chuck]: cannot open socket to send command...\n" );        return NULL;    }     if( strcmp( host, "127.0.0.1" ) )        EM_log( g_otf_log, "connecting to %s on port %i via TCP...", host, port );     if( !ck_connect( sock, host, (int)port ) )    {        CK_FPRINTF_STDERR( "cannot open TCP socket on %s:%i...\n", host, port );        ck_close( sock );        return NULL;    }     ck_send_timeout( sock, 0, 2000000 );     return sock;}    //-----------------------------------------------------------------------------// name: otf_send_cmd()// desc: ...//-----------------------------------------------------------------------------t_CKINT otf_send_cmd( t_CKINT argc, const char ** argv, t_CKINT & i,                      const char * host, t_CKINT port, t_CKINT * is_otf ){    Net_Msg msg;    // REFACTOR-2017 TODO: wat is global sigpipe mode//    g_sigpipe_mode = 1;    int tasks_total = 0, tasks_done = 0;    ck_socket dest = NULL;    if( is_otf ) *is_otf = TRUE;     // log    EM_log( CK_LOG_INFO, "examining otf command '%s'...", argv[i] );     if( !strcmp( argv[i], "--add" ) || !strcmp( argv[i], "+" ) )    {        if( ++i >= argc )        {            CK_FPRINTF_STDERR( "[chuck]: not enough arguments following [add]...\n" );            goto error;        }         if( !(dest = otf_send_connect( host, port )) ) return 0;        EM_pushlog();        do {            // log            EM_log( CK_LOG_INFO, "sending file:args '%s' for ADD...", mini(argv[i]) );            msg.type = MSG_ADD;            msg.param = 1;            tasks_done += otf_send_file( argv[i], msg, "add", dest );            tasks_total++;        } while( ++i < argc );        // log        EM_poplog();         if( !tasks_done )            goto error;    }    else if( !strcmp( argv[i], "--remove" ) || !strcmp( argv[i], "-" ) )    {        if( ++i >= argc )        {            CK_FPRINTF_STDERR( "[chuck]: not enough arguments following [remove]...\n" );            goto error;        }         if( !(dest = otf_send_connect( host, port )) ) return 0;        EM_pushlog();        do {            // log            EM_log( CK_LOG_INFO, "requesting REMOVE of shred '%i'..." );            msg.param = atoi( argv[i] );            msg.type = MSG_REMOVE;            otf_hton( &msg );            ck_send( dest, (char *)&msg, sizeof(msg) );        } while( ++i < argc );        // log        EM_poplog();    }    else if( !strcmp( argv[i], "--" ) )    {        if( !(dest = otf_send_connect( host, port )) ) return 0;        EM_pushlog();        // log        EM_log( CK_LOG_INFO, "requesting REMOVE LAST shred..." );        msg.param = CK_NO_VALUE;        msg.type = MSG_REMOVE;        otf_hton( &msg );        ck_send( dest, (char *)&msg, sizeof(msg) );        // log        EM_poplog();    }    else if( !strcmp( argv[i], "--replace" ) || !strcmp( argv[i], "=" ) )    {        if( ++i >= argc )        {            CK_FPRINTF_STDERR( "[chuck]: not enough arguments following [replace]...\n" );            goto error;        }         if( i <= 0 )            msg.param = CK_NO_VALUE;        else            msg.param = atoi( argv[i] );         if( ++i >= argc )        {            CK_FPRINTF_STDERR( "[chuck]: not enough arguments following [replace]...\n" );            goto error;        }         if( !(dest = otf_send_connect( host, port )) ) return 0;        EM_pushlog();        EM_log( CK_LOG_INFO, "requesting REPLACE shred '%i' with '%s'...", msg.param, mini(argv[i]) );        msg.type = MSG_REPLACE;        if( !otf_send_file( argv[i], msg, "replace", dest ) )            goto error;

Lines 1–500 of 782.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t