git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2681 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.90
| @@ -26,79 +26,79 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| namespace Jack | |||
| { | |||
| class JackNetDriver : public JackAudioDriver | |||
| { | |||
| private: | |||
| session_params_t fParams; | |||
| char* fMulticastIP; | |||
| JackNetSocket fSocket; | |||
| uint fNSubProcess; | |||
| jack_port_id_t* fMidiCapturePortList; | |||
| jack_port_id_t* fMidiPlaybackPortList; | |||
| packet_header_t fTxHeader; | |||
| packet_header_t fRxHeader; | |||
| char* fTxBuffer; | |||
| char* fRxBuffer; | |||
| char* fTxData; | |||
| char* fRxData; | |||
| NetMidiBuffer* fNetMidiCaptureBuffer; | |||
| NetMidiBuffer* fNetMidiPlaybackBuffer; | |||
| NetAudioBuffer* fNetAudioCaptureBuffer; | |||
| NetAudioBuffer* fNetAudioPlaybackBuffer; | |||
| int fAudioRxLen; | |||
| int fAudioTxLen; | |||
| bool Init(); | |||
| net_status_t GetNetMaster(); | |||
| net_status_t SendMasterStartSync(); | |||
| void Restart(); | |||
| int SetParams(); | |||
| int AllocPorts(); | |||
| int FreePorts(); | |||
| JackMidiBuffer* GetMidiInputBuffer ( int port_index ); | |||
| JackMidiBuffer* GetMidiOutputBuffer ( int port_index ); | |||
| int Recv ( size_t size, int flags ); | |||
| int Send ( size_t size, int flags ); | |||
| public: | |||
| JackNetDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, | |||
| const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports, const char* master_name ); | |||
| ~JackNetDriver(); | |||
| int Open ( jack_nframes_t frames_per_cycle, jack_nframes_t rate, bool capturing, bool playing, | |||
| int inchannels, int outchannels, bool monitor, const char* capture_driver_name, | |||
| const char* playback_driver_name, jack_nframes_t capture_latency, jack_nframes_t playback_latency ); | |||
| int Attach(); | |||
| int Detach(); | |||
| int Read(); | |||
| int Write(); | |||
| // BufferSize can be changed | |||
| bool IsFixedBufferSize() | |||
| { | |||
| return true; | |||
| } | |||
| int SetBufferSize(jack_nframes_t buffer_size) | |||
| { | |||
| return -1; | |||
| } | |||
| int SetSampleRate(jack_nframes_t sample_rate) | |||
| { | |||
| return -1; | |||
| } | |||
| }; | |||
| class JackNetDriver : public JackAudioDriver | |||
| { | |||
| private: | |||
| session_params_t fParams; | |||
| char* fMulticastIP; | |||
| JackNetSocket fSocket; | |||
| uint fNSubProcess; | |||
| jack_port_id_t* fMidiCapturePortList; | |||
| jack_port_id_t* fMidiPlaybackPortList; | |||
| packet_header_t fTxHeader; | |||
| packet_header_t fRxHeader; | |||
| char* fTxBuffer; | |||
| char* fRxBuffer; | |||
| char* fTxData; | |||
| char* fRxData; | |||
| NetMidiBuffer* fNetMidiCaptureBuffer; | |||
| NetMidiBuffer* fNetMidiPlaybackBuffer; | |||
| NetAudioBuffer* fNetAudioCaptureBuffer; | |||
| NetAudioBuffer* fNetAudioPlaybackBuffer; | |||
| int fAudioRxLen; | |||
| int fAudioTxLen; | |||
| bool Init(); | |||
| net_status_t GetNetMaster(); | |||
| net_status_t SendMasterStartSync(); | |||
| void Restart(); | |||
| int SetParams(); | |||
| int AllocPorts(); | |||
| int FreePorts(); | |||
| JackMidiBuffer* GetMidiInputBuffer ( int port_index ); | |||
| JackMidiBuffer* GetMidiOutputBuffer ( int port_index ); | |||
| int Recv ( size_t size, int flags ); | |||
| int Send ( size_t size, int flags ); | |||
| public: | |||
| JackNetDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, | |||
| const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports, const char* master_name ); | |||
| ~JackNetDriver(); | |||
| int Open ( jack_nframes_t frames_per_cycle, jack_nframes_t rate, bool capturing, bool playing, | |||
| int inchannels, int outchannels, bool monitor, const char* capture_driver_name, | |||
| const char* playback_driver_name, jack_nframes_t capture_latency, jack_nframes_t playback_latency ); | |||
| int Attach(); | |||
| int Detach(); | |||
| int Read(); | |||
| int Write(); | |||
| // BufferSize can be changed | |||
| bool IsFixedBufferSize() | |||
| { | |||
| return true; | |||
| } | |||
| int SetBufferSize(jack_nframes_t buffer_size) | |||
| { | |||
| return -1; | |||
| } | |||
| int SetSampleRate(jack_nframes_t sample_rate) | |||
| { | |||
| return -1; | |||
| } | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -21,95 +21,95 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #define __JACKNETMASTER_H__ | |||
| #include "JackNetTool.h" | |||
| #include "thread.h" | |||
| #include "jack.h" | |||
| #include "thread.h" | |||
| #include "jack.h" | |||
| #include "jslist.h" | |||
| #include <list> | |||
| namespace Jack | |||
| { | |||
| class JackNetMasterManager; | |||
| class JackNetMaster | |||
| { | |||
| friend class JackNetMasterManager; | |||
| private: | |||
| static int SetProcess ( jack_nframes_t nframes, void* arg ); | |||
| JackNetMasterManager* fMasterManager; | |||
| session_params_t fParams; | |||
| JackNetSocket fSocket; | |||
| uint fNSubProcess; | |||
| int fNetJumpCnt; | |||
| bool fRunning; | |||
| jack_client_t* fJackClient; | |||
| const char* fClientName; | |||
| jack_port_t** fAudioCapturePorts; | |||
| jack_port_t** fAudioPlaybackPorts; | |||
| jack_port_t** fMidiCapturePorts; | |||
| jack_port_t** fMidiPlaybackPorts; | |||
| packet_header_t fTxHeader; | |||
| packet_header_t fRxHeader; | |||
| char* fTxBuffer; | |||
| char* fRxBuffer; | |||
| char* fTxData; | |||
| char* fRxData; | |||
| NetAudioBuffer* fNetAudioCaptureBuffer; | |||
| NetAudioBuffer* fNetAudioPlaybackBuffer; | |||
| NetMidiBuffer* fNetMidiCaptureBuffer; | |||
| NetMidiBuffer* fNetMidiPlaybackBuffer; | |||
| int fAudioTxLen; | |||
| int fAudioRxLen; | |||
| bool Init(); | |||
| void FreePorts(); | |||
| void Exit(); | |||
| int Send ( char* buffer, size_t size, int flags ); | |||
| int Recv ( size_t size, int flags ); | |||
| int Process(); | |||
| public: | |||
| JackNetMaster ( JackNetMasterManager* manager, session_params_t& params ); | |||
| ~JackNetMaster (); | |||
| }; | |||
| typedef std::list<JackNetMaster*> master_list_t; | |||
| typedef master_list_t::iterator master_list_it_t; | |||
| class JackNetMasterManager | |||
| { | |||
| friend class JackNetMaster; | |||
| private: | |||
| static void* NetManagerThread ( void* arg ); | |||
| static int SetProcess ( jack_nframes_t nframes, void* arg ); | |||
| jack_client_t* fManagerClient; | |||
| const char* fManagerName; | |||
| const char* fMulticastIP; | |||
| JackNetSocket fSocket; | |||
| pthread_t fManagerThread; | |||
| master_list_t fMasterList; | |||
| uint32_t fGlobalID; | |||
| bool fRunning; | |||
| void Run(); | |||
| JackNetMaster* MasterInit ( session_params_t& params ); | |||
| master_list_it_t FindMaster ( uint32_t client_id ); | |||
| void KillMaster ( session_params_t* params ); | |||
| void SetSlaveName ( session_params_t& params ); | |||
| int Process(); | |||
| public: | |||
| JackNetMasterManager ( jack_client_t* jack_client, const JSList* params ); | |||
| ~JackNetMasterManager(); | |||
| void Exit(); | |||
| }; | |||
| class JackNetMasterManager; | |||
| class JackNetMaster | |||
| { | |||
| friend class JackNetMasterManager; | |||
| private: | |||
| static int SetProcess ( jack_nframes_t nframes, void* arg ); | |||
| JackNetMasterManager* fMasterManager; | |||
| session_params_t fParams; | |||
| JackNetSocket fSocket; | |||
| uint fNSubProcess; | |||
| int fNetJumpCnt; | |||
| bool fRunning; | |||
| jack_client_t* fJackClient; | |||
| const char* fClientName; | |||
| jack_port_t** fAudioCapturePorts; | |||
| jack_port_t** fAudioPlaybackPorts; | |||
| jack_port_t** fMidiCapturePorts; | |||
| jack_port_t** fMidiPlaybackPorts; | |||
| packet_header_t fTxHeader; | |||
| packet_header_t fRxHeader; | |||
| char* fTxBuffer; | |||
| char* fRxBuffer; | |||
| char* fTxData; | |||
| char* fRxData; | |||
| NetAudioBuffer* fNetAudioCaptureBuffer; | |||
| NetAudioBuffer* fNetAudioPlaybackBuffer; | |||
| NetMidiBuffer* fNetMidiCaptureBuffer; | |||
| NetMidiBuffer* fNetMidiPlaybackBuffer; | |||
| int fAudioTxLen; | |||
| int fAudioRxLen; | |||
| bool Init(); | |||
| void FreePorts(); | |||
| void Exit(); | |||
| int Send ( char* buffer, size_t size, int flags ); | |||
| int Recv ( size_t size, int flags ); | |||
| int Process(); | |||
| public: | |||
| JackNetMaster ( JackNetMasterManager* manager, session_params_t& params ); | |||
| ~JackNetMaster (); | |||
| }; | |||
| typedef std::list<JackNetMaster*> master_list_t; | |||
| typedef master_list_t::iterator master_list_it_t; | |||
| class JackNetMasterManager | |||
| { | |||
| friend class JackNetMaster; | |||
| private: | |||
| static void* NetManagerThread ( void* arg ); | |||
| static int SetProcess ( jack_nframes_t nframes, void* arg ); | |||
| jack_client_t* fManagerClient; | |||
| const char* fManagerName; | |||
| const char* fMulticastIP; | |||
| JackNetSocket fSocket; | |||
| pthread_t fManagerThread; | |||
| master_list_t fMasterList; | |||
| uint32_t fGlobalID; | |||
| bool fRunning; | |||
| void Run(); | |||
| JackNetMaster* MasterInit ( session_params_t& params ); | |||
| master_list_it_t FindMaster ( uint32_t client_id ); | |||
| void KillMaster ( session_params_t* params ); | |||
| void SetSlaveName ( session_params_t& params ); | |||
| int Process(); | |||
| public: | |||
| JackNetMasterManager ( jack_client_t* jack_client, const JSList* params ); | |||
| ~JackNetMasterManager(); | |||
| void Exit(); | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -25,330 +25,330 @@ namespace Jack | |||
| { | |||
| // NetMidiBuffer********************************************************************************** | |||
| NetMidiBuffer::NetMidiBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ) | |||
| { | |||
| fNPorts = nports; | |||
| fMaxBufsize = fNPorts * sizeof ( sample_t ) * params->fPeriodSize ; | |||
| fMaxPcktSize = params->fMtu - sizeof ( packet_header_t ); | |||
| fBuffer = new char[fMaxBufsize]; | |||
| fPortBuffer = new JackMidiBuffer* [fNPorts]; | |||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||
| fPortBuffer[port_index] = NULL; | |||
| fNetBuffer = net_buffer; | |||
| } | |||
| NetMidiBuffer::~NetMidiBuffer() | |||
| { | |||
| delete[] fBuffer; | |||
| delete[] fPortBuffer; | |||
| } | |||
| size_t NetMidiBuffer::GetSize() | |||
| { | |||
| return fMaxBufsize; | |||
| } | |||
| void NetMidiBuffer::DisplayEvents() | |||
| { | |||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||
| { | |||
| for ( uint event = 0; event < fPortBuffer[port_index]->event_count; event++ ) | |||
| if ( fPortBuffer[port_index]->IsValid() ) | |||
| jack_info ( "port %d : midi event %u/%u -> time : %u, size : %u", | |||
| port_index + 1, event + 1, fPortBuffer[port_index]->event_count, | |||
| fPortBuffer[port_index]->events[event].time, fPortBuffer[port_index]->events[event].size ); | |||
| } | |||
| } | |||
| int NetMidiBuffer::RenderFromJackPorts() | |||
| { | |||
| int pos = 0; | |||
| size_t copy_size; | |||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||
| { | |||
| copy_size = sizeof ( JackMidiBuffer ) + fPortBuffer[port_index]->event_count * sizeof ( JackMidiEvent ); | |||
| memcpy ( fBuffer + pos, fPortBuffer[port_index], copy_size ); | |||
| pos += copy_size; | |||
| memcpy ( fBuffer + pos, fPortBuffer[port_index] + ( fPortBuffer[port_index]->buffer_size - fPortBuffer[port_index]->write_pos ), | |||
| fPortBuffer[port_index]->write_pos ); | |||
| pos += fPortBuffer[port_index]->write_pos; | |||
| } | |||
| return pos; | |||
| } | |||
| int NetMidiBuffer::RenderToJackPorts() | |||
| { | |||
| int pos = 0; | |||
| int copy_size; | |||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||
| { | |||
| copy_size = sizeof ( JackMidiBuffer ) + reinterpret_cast<JackMidiBuffer*> ( fBuffer + pos )->event_count * sizeof ( JackMidiEvent ); | |||
| memcpy ( fPortBuffer[port_index], fBuffer + pos, copy_size ); | |||
| pos += copy_size; | |||
| memcpy ( fPortBuffer[port_index] + ( fPortBuffer[port_index]->buffer_size - fPortBuffer[port_index]->write_pos ), | |||
| fBuffer + pos, fPortBuffer[port_index]->write_pos ); | |||
| pos += fPortBuffer[port_index]->write_pos; | |||
| } | |||
| return pos; | |||
| } | |||
| int NetMidiBuffer::RenderFromNetwork ( int subcycle, size_t copy_size ) | |||
| { | |||
| memcpy ( fBuffer + subcycle * fMaxPcktSize, fNetBuffer, copy_size ); | |||
| return copy_size; | |||
| } | |||
| int NetMidiBuffer::RenderToNetwork ( int subcycle, size_t total_size ) | |||
| { | |||
| int size = total_size - subcycle * fMaxPcktSize; | |||
| int copy_size = ( size <= fMaxPcktSize ) ? size : fMaxPcktSize; | |||
| memcpy ( fNetBuffer, fBuffer + subcycle * fMaxPcktSize, copy_size ); | |||
| return copy_size; | |||
| } | |||
| NetMidiBuffer::NetMidiBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ) | |||
| { | |||
| fNPorts = nports; | |||
| fMaxBufsize = fNPorts * sizeof ( sample_t ) * params->fPeriodSize ; | |||
| fMaxPcktSize = params->fMtu - sizeof ( packet_header_t ); | |||
| fBuffer = new char[fMaxBufsize]; | |||
| fPortBuffer = new JackMidiBuffer* [fNPorts]; | |||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||
| fPortBuffer[port_index] = NULL; | |||
| fNetBuffer = net_buffer; | |||
| } | |||
| NetMidiBuffer::~NetMidiBuffer() | |||
| { | |||
| delete[] fBuffer; | |||
| delete[] fPortBuffer; | |||
| } | |||
| size_t NetMidiBuffer::GetSize() | |||
| { | |||
| return fMaxBufsize; | |||
| } | |||
| void NetMidiBuffer::DisplayEvents() | |||
| { | |||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||
| { | |||
| for ( uint event = 0; event < fPortBuffer[port_index]->event_count; event++ ) | |||
| if ( fPortBuffer[port_index]->IsValid() ) | |||
| jack_info ( "port %d : midi event %u/%u -> time : %u, size : %u", | |||
| port_index + 1, event + 1, fPortBuffer[port_index]->event_count, | |||
| fPortBuffer[port_index]->events[event].time, fPortBuffer[port_index]->events[event].size ); | |||
| } | |||
| } | |||
| int NetMidiBuffer::RenderFromJackPorts() | |||
| { | |||
| int pos = 0; | |||
| size_t copy_size; | |||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||
| { | |||
| copy_size = sizeof ( JackMidiBuffer ) + fPortBuffer[port_index]->event_count * sizeof ( JackMidiEvent ); | |||
| memcpy ( fBuffer + pos, fPortBuffer[port_index], copy_size ); | |||
| pos += copy_size; | |||
| memcpy ( fBuffer + pos, fPortBuffer[port_index] + ( fPortBuffer[port_index]->buffer_size - fPortBuffer[port_index]->write_pos ), | |||
| fPortBuffer[port_index]->write_pos ); | |||
| pos += fPortBuffer[port_index]->write_pos; | |||
| } | |||
| return pos; | |||
| } | |||
| int NetMidiBuffer::RenderToJackPorts() | |||
| { | |||
| int pos = 0; | |||
| int copy_size; | |||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||
| { | |||
| copy_size = sizeof ( JackMidiBuffer ) + reinterpret_cast<JackMidiBuffer*> ( fBuffer + pos )->event_count * sizeof ( JackMidiEvent ); | |||
| memcpy ( fPortBuffer[port_index], fBuffer + pos, copy_size ); | |||
| pos += copy_size; | |||
| memcpy ( fPortBuffer[port_index] + ( fPortBuffer[port_index]->buffer_size - fPortBuffer[port_index]->write_pos ), | |||
| fBuffer + pos, fPortBuffer[port_index]->write_pos ); | |||
| pos += fPortBuffer[port_index]->write_pos; | |||
| } | |||
| return pos; | |||
| } | |||
| int NetMidiBuffer::RenderFromNetwork ( int subcycle, size_t copy_size ) | |||
| { | |||
| memcpy ( fBuffer + subcycle * fMaxPcktSize, fNetBuffer, copy_size ); | |||
| return copy_size; | |||
| } | |||
| int NetMidiBuffer::RenderToNetwork ( int subcycle, size_t total_size ) | |||
| { | |||
| int size = total_size - subcycle * fMaxPcktSize; | |||
| int copy_size = ( size <= fMaxPcktSize ) ? size : fMaxPcktSize; | |||
| memcpy ( fNetBuffer, fBuffer + subcycle * fMaxPcktSize, copy_size ); | |||
| return copy_size; | |||
| } | |||
| // net audio buffer ********************************************************************************* | |||
| NetAudioBuffer::NetAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ) | |||
| { | |||
| fNPorts = nports; | |||
| fPeriodSize = params->fPeriodSize; | |||
| fSubPeriodSize = params->fFramesPerPacket; | |||
| fSubPeriodBytesSize = fSubPeriodSize * sizeof ( sample_t ); | |||
| fPortBuffer = new sample_t* [fNPorts]; | |||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||
| fPortBuffer[port_index] = NULL; | |||
| fNetBuffer = net_buffer; | |||
| } | |||
| NetAudioBuffer::~NetAudioBuffer() | |||
| { | |||
| delete[] fPortBuffer; | |||
| } | |||
| size_t NetAudioBuffer::GetSize() | |||
| { | |||
| return fNPorts * fSubPeriodBytesSize; | |||
| } | |||
| void NetAudioBuffer::RenderFromJackPorts ( int subcycle ) | |||
| { | |||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||
| memcpy ( fNetBuffer + port_index * fSubPeriodBytesSize, fPortBuffer[port_index] + subcycle * fSubPeriodSize, fSubPeriodBytesSize ); | |||
| } | |||
| void NetAudioBuffer::RenderToJackPorts ( int subcycle ) | |||
| { | |||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||
| memcpy ( fPortBuffer[port_index] + subcycle * fSubPeriodSize, fNetBuffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize ); | |||
| } | |||
| NetAudioBuffer::NetAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ) | |||
| { | |||
| fNPorts = nports; | |||
| fPeriodSize = params->fPeriodSize; | |||
| fSubPeriodSize = params->fFramesPerPacket; | |||
| fSubPeriodBytesSize = fSubPeriodSize * sizeof ( sample_t ); | |||
| fPortBuffer = new sample_t* [fNPorts]; | |||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||
| fPortBuffer[port_index] = NULL; | |||
| fNetBuffer = net_buffer; | |||
| } | |||
| NetAudioBuffer::~NetAudioBuffer() | |||
| { | |||
| delete[] fPortBuffer; | |||
| } | |||
| size_t NetAudioBuffer::GetSize() | |||
| { | |||
| return fNPorts * fSubPeriodBytesSize; | |||
| } | |||
| void NetAudioBuffer::RenderFromJackPorts ( int subcycle ) | |||
| { | |||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||
| memcpy ( fNetBuffer + port_index * fSubPeriodBytesSize, fPortBuffer[port_index] + subcycle * fSubPeriodSize, fSubPeriodBytesSize ); | |||
| } | |||
| void NetAudioBuffer::RenderToJackPorts ( int subcycle ) | |||
| { | |||
| for ( int port_index = 0; port_index < fNPorts; port_index++ ) | |||
| memcpy ( fPortBuffer[port_index] + subcycle * fSubPeriodSize, fNetBuffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize ); | |||
| } | |||
| // SessionParams ************************************************************************************ | |||
| EXPORT void SessionParamsHToN ( session_params_t* params ) | |||
| { | |||
| params->fPacketID = htonl ( params->fPacketID ); | |||
| params->fMtu = htonl ( params->fMtu ); | |||
| params->fID = htonl ( params->fID ); | |||
| params->fSendAudioChannels = htonl ( params->fSendAudioChannels ); | |||
| params->fReturnAudioChannels = htonl ( params->fReturnAudioChannels ); | |||
| params->fSendMidiChannels = htonl ( params->fSendMidiChannels ); | |||
| params->fReturnMidiChannels = htonl ( params->fReturnMidiChannels ); | |||
| params->fSampleRate = htonl ( params->fSampleRate ); | |||
| params->fPeriodSize = htonl ( params->fPeriodSize ); | |||
| params->fFramesPerPacket = htonl ( params->fFramesPerPacket ); | |||
| params->fBitdepth = htonl ( params->fBitdepth ); | |||
| } | |||
| EXPORT void SessionParamsNToH ( session_params_t* params ) | |||
| { | |||
| params->fPacketID = ntohl ( params->fPacketID ); | |||
| params->fMtu = ntohl ( params->fMtu ); | |||
| params->fID = ntohl ( params->fID ); | |||
| params->fSendAudioChannels = ntohl ( params->fSendAudioChannels ); | |||
| params->fReturnAudioChannels = ntohl ( params->fReturnAudioChannels ); | |||
| params->fSendMidiChannels = ntohl ( params->fSendMidiChannels ); | |||
| params->fReturnMidiChannels = ntohl ( params->fReturnMidiChannels ); | |||
| params->fSampleRate = ntohl ( params->fSampleRate ); | |||
| params->fPeriodSize = ntohl ( params->fPeriodSize ); | |||
| params->fFramesPerPacket = ntohl ( params->fFramesPerPacket ); | |||
| params->fBitdepth = ntohl ( params->fBitdepth ); | |||
| } | |||
| EXPORT void SessionParamsDisplay ( session_params_t* params ) | |||
| { | |||
| jack_info ( "---->Network parameters of '%s'<----", params->fName ); | |||
| jack_info ( "Protocol revision : %c", params->fProtocolVersion ); | |||
| jack_info ( "MTU : %u", params->fMtu ); | |||
| jack_info ( "Master name : %s", params->fMasterNetName ); | |||
| jack_info ( "Slave name : %s", params->fSlaveNetName ); | |||
| jack_info ( "ID : %u", params->fID ); | |||
| jack_info ( "Send channels (audio - midi) : %d - %d", params->fSendAudioChannels, params->fSendMidiChannels ); | |||
| jack_info ( "Return channels (audio - midi) : %d - %d", params->fReturnAudioChannels, params->fReturnMidiChannels ); | |||
| jack_info ( "Sample rate : %u frames per second", params->fSampleRate ); | |||
| jack_info ( "Period size : %u frames per period", params->fPeriodSize ); | |||
| jack_info ( "Frames per packet : %u", params->fFramesPerPacket ); | |||
| jack_info ( "Packet per period : %u", params->fPeriodSize / params->fFramesPerPacket ); | |||
| jack_info ( "Bitdepth (0 for float) : %u", params->fBitdepth ); | |||
| jack_info ( "Name : %s", params->fName ); | |||
| jack_info ( "---------------------------------------------" ); | |||
| } | |||
| EXPORT sync_packet_type_t GetPacketType ( session_params_t* params ) | |||
| { | |||
| switch ( params->fPacketID ) | |||
| { | |||
| case 0: | |||
| return SLAVE_AVAILABLE; | |||
| case 1: | |||
| return SLAVE_SETUP; | |||
| case 2: | |||
| return START_MASTER; | |||
| case 3: | |||
| return START_SLAVE; | |||
| case 4: | |||
| return KILL_MASTER; | |||
| } | |||
| return INVALID; | |||
| } | |||
| EXPORT int SetPacketType ( session_params_t* params, sync_packet_type_t packet_type ) | |||
| { | |||
| switch ( packet_type ) | |||
| { | |||
| case INVALID: | |||
| return -1; | |||
| case SLAVE_AVAILABLE: | |||
| params->fPacketID = 0; | |||
| break; | |||
| case SLAVE_SETUP: | |||
| params->fPacketID = 1; | |||
| break; | |||
| case START_MASTER: | |||
| params->fPacketID = 2; | |||
| break; | |||
| case START_SLAVE: | |||
| params->fPacketID = 3; | |||
| break; | |||
| case KILL_MASTER: | |||
| params->fPacketID = 4; | |||
| } | |||
| return 0; | |||
| } | |||
| EXPORT void SessionParamsHToN ( session_params_t* params ) | |||
| { | |||
| params->fPacketID = htonl ( params->fPacketID ); | |||
| params->fMtu = htonl ( params->fMtu ); | |||
| params->fID = htonl ( params->fID ); | |||
| params->fSendAudioChannels = htonl ( params->fSendAudioChannels ); | |||
| params->fReturnAudioChannels = htonl ( params->fReturnAudioChannels ); | |||
| params->fSendMidiChannels = htonl ( params->fSendMidiChannels ); | |||
| params->fReturnMidiChannels = htonl ( params->fReturnMidiChannels ); | |||
| params->fSampleRate = htonl ( params->fSampleRate ); | |||
| params->fPeriodSize = htonl ( params->fPeriodSize ); | |||
| params->fFramesPerPacket = htonl ( params->fFramesPerPacket ); | |||
| params->fBitdepth = htonl ( params->fBitdepth ); | |||
| } | |||
| EXPORT void SessionParamsNToH ( session_params_t* params ) | |||
| { | |||
| params->fPacketID = ntohl ( params->fPacketID ); | |||
| params->fMtu = ntohl ( params->fMtu ); | |||
| params->fID = ntohl ( params->fID ); | |||
| params->fSendAudioChannels = ntohl ( params->fSendAudioChannels ); | |||
| params->fReturnAudioChannels = ntohl ( params->fReturnAudioChannels ); | |||
| params->fSendMidiChannels = ntohl ( params->fSendMidiChannels ); | |||
| params->fReturnMidiChannels = ntohl ( params->fReturnMidiChannels ); | |||
| params->fSampleRate = ntohl ( params->fSampleRate ); | |||
| params->fPeriodSize = ntohl ( params->fPeriodSize ); | |||
| params->fFramesPerPacket = ntohl ( params->fFramesPerPacket ); | |||
| params->fBitdepth = ntohl ( params->fBitdepth ); | |||
| } | |||
| EXPORT void SessionParamsDisplay ( session_params_t* params ) | |||
| { | |||
| jack_info ( "---->Network parameters of '%s'<----", params->fName ); | |||
| jack_info ( "Protocol revision : %c", params->fProtocolVersion ); | |||
| jack_info ( "MTU : %u", params->fMtu ); | |||
| jack_info ( "Master name : %s", params->fMasterNetName ); | |||
| jack_info ( "Slave name : %s", params->fSlaveNetName ); | |||
| jack_info ( "ID : %u", params->fID ); | |||
| jack_info ( "Send channels (audio - midi) : %d - %d", params->fSendAudioChannels, params->fSendMidiChannels ); | |||
| jack_info ( "Return channels (audio - midi) : %d - %d", params->fReturnAudioChannels, params->fReturnMidiChannels ); | |||
| jack_info ( "Sample rate : %u frames per second", params->fSampleRate ); | |||
| jack_info ( "Period size : %u frames per period", params->fPeriodSize ); | |||
| jack_info ( "Frames per packet : %u", params->fFramesPerPacket ); | |||
| jack_info ( "Packet per period : %u", params->fPeriodSize / params->fFramesPerPacket ); | |||
| jack_info ( "Bitdepth (0 for float) : %u", params->fBitdepth ); | |||
| jack_info ( "Name : %s", params->fName ); | |||
| jack_info ( "---------------------------------------------" ); | |||
| } | |||
| EXPORT sync_packet_type_t GetPacketType ( session_params_t* params ) | |||
| { | |||
| switch ( params->fPacketID ) | |||
| { | |||
| case 0: | |||
| return SLAVE_AVAILABLE; | |||
| case 1: | |||
| return SLAVE_SETUP; | |||
| case 2: | |||
| return START_MASTER; | |||
| case 3: | |||
| return START_SLAVE; | |||
| case 4: | |||
| return KILL_MASTER; | |||
| } | |||
| return INVALID; | |||
| } | |||
| EXPORT int SetPacketType ( session_params_t* params, sync_packet_type_t packet_type ) | |||
| { | |||
| switch ( packet_type ) | |||
| { | |||
| case INVALID: | |||
| return -1; | |||
| case SLAVE_AVAILABLE: | |||
| params->fPacketID = 0; | |||
| break; | |||
| case SLAVE_SETUP: | |||
| params->fPacketID = 1; | |||
| break; | |||
| case START_MASTER: | |||
| params->fPacketID = 2; | |||
| break; | |||
| case START_SLAVE: | |||
| params->fPacketID = 3; | |||
| break; | |||
| case KILL_MASTER: | |||
| params->fPacketID = 4; | |||
| } | |||
| return 0; | |||
| } | |||
| // Packet header ********************************************************************************** | |||
| EXPORT void PacketHeaderHToN ( packet_header_t* header ) | |||
| { | |||
| header->fID = htonl ( header->fID ); | |||
| header->fMidiDataSize = htonl ( header->fMidiDataSize ); | |||
| header->fBitdepth = htonl ( header->fBitdepth ); | |||
| header->fNMidiPckt = htonl ( header->fNMidiPckt ); | |||
| header->fCycle = ntohl ( header->fCycle ); | |||
| header->fSubCycle = htonl ( header->fSubCycle ); | |||
| } | |||
| EXPORT void PacketHeaderNToH ( packet_header_t* header ) | |||
| { | |||
| header->fID = ntohl ( header->fID ); | |||
| header->fMidiDataSize = ntohl ( header->fMidiDataSize ); | |||
| header->fBitdepth = ntohl ( header->fBitdepth ); | |||
| header->fNMidiPckt = ntohl ( header->fNMidiPckt ); | |||
| header->fCycle = ntohl ( header->fCycle ); | |||
| header->fSubCycle = ntohl ( header->fSubCycle ); | |||
| } | |||
| EXPORT void PacketHeaderDisplay ( packet_header_t* header ) | |||
| { | |||
| jack_info ( "********************Header********************" ); | |||
| jack_info ( "Data type : %c", header->fDataType ); | |||
| jack_info ( "Data stream : %c", header->fDataStream ); | |||
| jack_info ( "ID : %u", header->fID ); | |||
| jack_info ( "Cycle : %u", header->fCycle ); | |||
| jack_info ( "SubCycle : %u", header->fSubCycle ); | |||
| jack_info ( "Midi packets : %u", header->fNMidiPckt ); | |||
| jack_info ( "Midi data size : %u", header->fMidiDataSize ); | |||
| jack_info ( "Last packet : '%c'", header->fIsLastPckt ); | |||
| jack_info ( "Bitdepth : %u (0 for float)", header->fBitdepth ); | |||
| jack_info ( "**********************************************" ); | |||
| } | |||
| EXPORT void PacketHeaderHToN ( packet_header_t* header ) | |||
| { | |||
| header->fID = htonl ( header->fID ); | |||
| header->fMidiDataSize = htonl ( header->fMidiDataSize ); | |||
| header->fBitdepth = htonl ( header->fBitdepth ); | |||
| header->fNMidiPckt = htonl ( header->fNMidiPckt ); | |||
| header->fCycle = ntohl ( header->fCycle ); | |||
| header->fSubCycle = htonl ( header->fSubCycle ); | |||
| } | |||
| EXPORT void PacketHeaderNToH ( packet_header_t* header ) | |||
| { | |||
| header->fID = ntohl ( header->fID ); | |||
| header->fMidiDataSize = ntohl ( header->fMidiDataSize ); | |||
| header->fBitdepth = ntohl ( header->fBitdepth ); | |||
| header->fNMidiPckt = ntohl ( header->fNMidiPckt ); | |||
| header->fCycle = ntohl ( header->fCycle ); | |||
| header->fSubCycle = ntohl ( header->fSubCycle ); | |||
| } | |||
| EXPORT void PacketHeaderDisplay ( packet_header_t* header ) | |||
| { | |||
| jack_info ( "********************Header********************" ); | |||
| jack_info ( "Data type : %c", header->fDataType ); | |||
| jack_info ( "Data stream : %c", header->fDataStream ); | |||
| jack_info ( "ID : %u", header->fID ); | |||
| jack_info ( "Cycle : %u", header->fCycle ); | |||
| jack_info ( "SubCycle : %u", header->fSubCycle ); | |||
| jack_info ( "Midi packets : %u", header->fNMidiPckt ); | |||
| jack_info ( "Midi data size : %u", header->fMidiDataSize ); | |||
| jack_info ( "Last packet : '%c'", header->fIsLastPckt ); | |||
| jack_info ( "Bitdepth : %u (0 for float)", header->fBitdepth ); | |||
| jack_info ( "**********************************************" ); | |||
| } | |||
| // Utility ******************************************************************************************************* | |||
| EXPORT int SocketAPIInit() | |||
| { | |||
| #ifdef WIN32 | |||
| WORD wVersionRequested = MAKEWORD ( 2, 2 ); | |||
| WSADATA wsaData; | |||
| if ( WSAStartup(wVersionRequested, &wsaData) != 0 ) | |||
| { | |||
| jack_error ( "WSAStartup error : %s", strerror ( NET_ERROR_CODE ) ); | |||
| return -1; | |||
| } | |||
| if ( LOBYTE ( wsaData.wVersion ) != 2 || HIBYTE ( wsaData.wVersion ) != 2 ) | |||
| { | |||
| jack_error ( "Could not find a useable version of Winsock.dll\n" ); | |||
| WSACleanup(); | |||
| return -1; | |||
| } | |||
| #endif | |||
| return 0; | |||
| } | |||
| EXPORT int SocketAPIEnd() | |||
| { | |||
| #ifdef WIN32 | |||
| return WSACleanup(); | |||
| #endif | |||
| return 0; | |||
| } | |||
| EXPORT jack_nframes_t SetFramesPerPacket ( session_params_t* params ) | |||
| { | |||
| if ( !params->fSendAudioChannels && !params->fReturnAudioChannels ) | |||
| return ( params->fFramesPerPacket = params->fPeriodSize ); | |||
| size_t period = ( int ) powf ( 2.f, ( int ) ( log ( ( params->fMtu - sizeof ( packet_header_t ) ) | |||
| / ( max ( params->fReturnAudioChannels, params->fSendAudioChannels ) * sizeof ( sample_t ) ) ) / log ( 2 ) ) ); | |||
| ( period > params->fPeriodSize ) ? params->fFramesPerPacket = params->fPeriodSize : params->fFramesPerPacket = period; | |||
| return params->fFramesPerPacket; | |||
| } | |||
| EXPORT int GetNMidiPckt ( session_params_t* params, size_t data_size ) | |||
| { | |||
| //even if there is no midi data, jack need an empty buffer to know there is no event to read | |||
| //99% of the cases : all data in one packet | |||
| if ( data_size <= ( params->fMtu - sizeof ( packet_header_t ) ) ) | |||
| return 1; | |||
| //else, get the number of needed packets (simply slice the biiig buffer) | |||
| int npckt = data_size / ( params->fMtu - sizeof ( packet_header_t ) ); | |||
| if ( data_size % ( params->fMtu - sizeof ( packet_header_t ) ) ) | |||
| return ++npckt; | |||
| return npckt; | |||
| } | |||
| EXPORT int SetRxTimeout ( JackNetSocket* socket, session_params_t* params ) | |||
| { | |||
| //time in ms : 1,25 * 'one packet time' | |||
| float time = 1250 * ( static_cast<float> ( params->fFramesPerPacket ) / static_cast<float> ( params->fSampleRate ) ); | |||
| int ms = ( int ) time; | |||
| return ( socket->SetTimeOut ( ms ) == SOCKET_ERROR ) ? SOCKET_ERROR : ms; | |||
| } | |||
| EXPORT int SocketAPIInit() | |||
| { | |||
| #ifdef WIN32 | |||
| WORD wVersionRequested = MAKEWORD ( 2, 2 ); | |||
| WSADATA wsaData; | |||
| if ( WSAStartup(wVersionRequested, &wsaData) != 0 ) | |||
| { | |||
| jack_error ( "WSAStartup error : %s", strerror ( NET_ERROR_CODE ) ); | |||
| return -1; | |||
| } | |||
| if ( LOBYTE ( wsaData.wVersion ) != 2 || HIBYTE ( wsaData.wVersion ) != 2 ) | |||
| { | |||
| jack_error ( "Could not find a useable version of Winsock.dll\n" ); | |||
| WSACleanup(); | |||
| return -1; | |||
| } | |||
| #endif | |||
| return 0; | |||
| } | |||
| EXPORT int SocketAPIEnd() | |||
| { | |||
| #ifdef WIN32 | |||
| return WSACleanup(); | |||
| #endif | |||
| return 0; | |||
| } | |||
| EXPORT jack_nframes_t SetFramesPerPacket ( session_params_t* params ) | |||
| { | |||
| if ( !params->fSendAudioChannels && !params->fReturnAudioChannels ) | |||
| return ( params->fFramesPerPacket = params->fPeriodSize ); | |||
| size_t period = ( int ) powf ( 2.f, ( int ) ( log ( ( params->fMtu - sizeof ( packet_header_t ) ) | |||
| / ( max ( params->fReturnAudioChannels, params->fSendAudioChannels ) * sizeof ( sample_t ) ) ) / log ( 2 ) ) ); | |||
| ( period > params->fPeriodSize ) ? params->fFramesPerPacket = params->fPeriodSize : params->fFramesPerPacket = period; | |||
| return params->fFramesPerPacket; | |||
| } | |||
| EXPORT int GetNMidiPckt ( session_params_t* params, size_t data_size ) | |||
| { | |||
| //even if there is no midi data, jack need an empty buffer to know there is no event to read | |||
| //99% of the cases : all data in one packet | |||
| if ( data_size <= ( params->fMtu - sizeof ( packet_header_t ) ) ) | |||
| return 1; | |||
| //else, get the number of needed packets (simply slice the biiig buffer) | |||
| int npckt = data_size / ( params->fMtu - sizeof ( packet_header_t ) ); | |||
| if ( data_size % ( params->fMtu - sizeof ( packet_header_t ) ) ) | |||
| return ++npckt; | |||
| return npckt; | |||
| } | |||
| EXPORT int SetRxTimeout ( JackNetSocket* socket, session_params_t* params ) | |||
| { | |||
| //time in ms : 1,25 * 'one packet time' | |||
| float time = 1250 * ( static_cast<float> ( params->fFramesPerPacket ) / static_cast<float> ( params->fSampleRate ) ); | |||
| int ms = ( int ) time; | |||
| return ( socket->SetTimeOut ( ms ) == SOCKET_ERROR ) ? SOCKET_ERROR : ms; | |||
| } | |||
| // Packet ******************************************************************************************************* | |||
| EXPORT bool IsNextPacket ( packet_header_t* previous, packet_header_t* next, uint subcycles ) | |||
| { | |||
| //ignore first cycle | |||
| if ( previous->fCycle <= 1 ) | |||
| return true; | |||
| //same PcktID (cycle), next SubPcktID (subcycle) | |||
| if ( ( previous->fSubCycle < ( subcycles - 1 ) ) && ( next->fCycle == previous->fCycle ) && ( next->fSubCycle == ( previous->fSubCycle + 1 ) ) ) | |||
| return true; | |||
| //next PcktID (cycle), SubPcktID reset to 1 (first subcyle) | |||
| if ( ( next->fCycle == ( previous->fCycle + 1 ) ) && ( previous->fSubCycle == ( subcycles - 1 ) ) && ( next->fSubCycle == 0 ) ) | |||
| return true; | |||
| //else, next is'nt next, return false | |||
| return false; | |||
| } | |||
| EXPORT bool IsNextPacket ( packet_header_t* previous, packet_header_t* next, uint subcycles ) | |||
| { | |||
| //ignore first cycle | |||
| if ( previous->fCycle <= 1 ) | |||
| return true; | |||
| //same PcktID (cycle), next SubPcktID (subcycle) | |||
| if ( ( previous->fSubCycle < ( subcycles - 1 ) ) && ( next->fCycle == previous->fCycle ) && ( next->fSubCycle == ( previous->fSubCycle + 1 ) ) ) | |||
| return true; | |||
| //next PcktID (cycle), SubPcktID reset to 1 (first subcyle) | |||
| if ( ( next->fCycle == ( previous->fCycle + 1 ) ) && ( previous->fSubCycle == ( subcycles - 1 ) ) && ( next->fSubCycle == 0 ) ) | |||
| return true; | |||
| //else, next is'nt next, return false | |||
| return false; | |||
| } | |||
| } | |||
| @@ -21,7 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include "JackConstants.h" | |||
| #include "JackMidiPort.h" | |||
| #include "JackExports.h" | |||
| #include "JackError.h" | |||
| #include "JackError.h" | |||
| #include "JackTools.h" | |||
| #include "JackPlatformNetSocket.h" | |||
| @@ -31,157 +31,157 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| namespace Jack | |||
| { | |||
| typedef struct _session_params session_params_t; | |||
| typedef struct _packet_header packet_header_t; | |||
| typedef struct sockaddr socket_address_t; | |||
| typedef struct in_addr address_t; | |||
| typedef jack_default_audio_sample_t sample_t; | |||
| typedef struct _session_params session_params_t; | |||
| typedef struct _packet_header packet_header_t; | |||
| typedef struct sockaddr socket_address_t; | |||
| typedef struct in_addr address_t; | |||
| typedef jack_default_audio_sample_t sample_t; | |||
| //session params ****************************************************************************** | |||
| struct _session_params | |||
| { | |||
| char fPacketType[7]; //packet type ('param') | |||
| char fProtocolVersion; //version | |||
| uint32_t fPacketID; //indicates the packet type | |||
| char fMasterNetName[256]; //master hostname (network) | |||
| char fSlaveNetName[256]; //slave hostname (network) | |||
| uint32_t fMtu; //connection mtu | |||
| uint32_t fID; //slave's ID | |||
| uint32_t fSendAudioChannels; //number of master->slave channels | |||
| uint32_t fReturnAudioChannels; //number of slave->master channels | |||
| uint32_t fSendMidiChannels; //number of master->slave midi channels | |||
| uint32_t fReturnMidiChannels; //number of slave->master midi channels | |||
| uint32_t fSampleRate; //session sample rate | |||
| uint32_t fPeriodSize; //period size | |||
| uint32_t fFramesPerPacket; //complete frames per packet | |||
| uint32_t fBitdepth; //samples bitdepth (unused) | |||
| char fName[JACK_CLIENT_NAME_SIZE]; //slave's name | |||
| }; | |||
| struct _session_params | |||
| { | |||
| char fPacketType[7]; //packet type ('param') | |||
| char fProtocolVersion; //version | |||
| uint32_t fPacketID; //indicates the packet type | |||
| char fMasterNetName[256]; //master hostname (network) | |||
| char fSlaveNetName[256]; //slave hostname (network) | |||
| uint32_t fMtu; //connection mtu | |||
| uint32_t fID; //slave's ID | |||
| uint32_t fSendAudioChannels; //number of master->slave channels | |||
| uint32_t fReturnAudioChannels; //number of slave->master channels | |||
| uint32_t fSendMidiChannels; //number of master->slave midi channels | |||
| uint32_t fReturnMidiChannels; //number of slave->master midi channels | |||
| uint32_t fSampleRate; //session sample rate | |||
| uint32_t fPeriodSize; //period size | |||
| uint32_t fFramesPerPacket; //complete frames per packet | |||
| uint32_t fBitdepth; //samples bitdepth (unused) | |||
| char fName[JACK_CLIENT_NAME_SIZE]; //slave's name | |||
| }; | |||
| //net status ********************************************************************************** | |||
| enum _net_status | |||
| { | |||
| NET_SOCKET_ERROR = 0, | |||
| NET_CONNECT_ERROR, | |||
| NET_ERROR, | |||
| NET_SEND_ERROR, | |||
| NET_RECV_ERROR, | |||
| NET_CONNECTED, | |||
| NET_ROLLING | |||
| }; | |||
| enum _net_status | |||
| { | |||
| NET_SOCKET_ERROR = 0, | |||
| NET_CONNECT_ERROR, | |||
| NET_ERROR, | |||
| NET_SEND_ERROR, | |||
| NET_RECV_ERROR, | |||
| NET_CONNECTED, | |||
| NET_ROLLING | |||
| }; | |||
| typedef enum _net_status net_status_t; | |||
| typedef enum _net_status net_status_t; | |||
| //sync packet type **************************************************************************** | |||
| enum _sync_packet_type | |||
| { | |||
| INVALID = 0, //... | |||
| SLAVE_AVAILABLE, //a slave is available | |||
| SLAVE_SETUP, //slave configuration | |||
| START_MASTER, //slave is ready, start master | |||
| START_SLAVE, //master is ready, activate slave | |||
| KILL_MASTER //master must stop | |||
| }; | |||
| enum _sync_packet_type | |||
| { | |||
| INVALID = 0, //... | |||
| SLAVE_AVAILABLE, //a slave is available | |||
| SLAVE_SETUP, //slave configuration | |||
| START_MASTER, //slave is ready, start master | |||
| START_SLAVE, //master is ready, activate slave | |||
| KILL_MASTER //master must stop | |||
| }; | |||
| typedef enum _sync_packet_type sync_packet_type_t; | |||
| typedef enum _sync_packet_type sync_packet_type_t; | |||
| //packet header ******************************************************************************* | |||
| struct _packet_header | |||
| { | |||
| char fPacketType[7]; //packet type ( 'headr' ) | |||
| char fDataType; //a for audio, m for midi | |||
| char fDataStream; //s for send, r for return | |||
| uint32_t fID; //to identify the slave | |||
| uint32_t fBitdepth; //bitdepth of the data samples | |||
| uint32_t fMidiDataSize; //size of midi data (if packet is 'midi typed') in bytes | |||
| uint32_t fNMidiPckt; //number of midi packets of the cycle | |||
| uint32_t fCycle; //process cycle counter | |||
| uint32_t fSubCycle; //midi/audio subcycle counter | |||
| char fIsLastPckt; //is it the last packet of a given cycle ('y' or 'n') | |||
| char fFree[13]; //unused | |||
| }; | |||
| struct _packet_header | |||
| { | |||
| char fPacketType[7]; //packet type ( 'headr' ) | |||
| char fDataType; //a for audio, m for midi | |||
| char fDataStream; //s for send, r for return | |||
| uint32_t fID; //to identify the slave | |||
| uint32_t fBitdepth; //bitdepth of the data samples | |||
| uint32_t fMidiDataSize; //size of midi data (if packet is 'midi typed') in bytes | |||
| uint32_t fNMidiPckt; //number of midi packets of the cycle | |||
| uint32_t fCycle; //process cycle counter | |||
| uint32_t fSubCycle; //midi/audio subcycle counter | |||
| char fIsLastPckt; //is it the last packet of a given cycle ('y' or 'n') | |||
| char fFree[13]; //unused | |||
| }; | |||
| //midi data *********************************************************************************** | |||
| class EXPORT NetMidiBuffer | |||
| { | |||
| private: | |||
| int fNPorts; | |||
| size_t fMaxBufsize; | |||
| int fMaxPcktSize; | |||
| //data | |||
| char* fBuffer; | |||
| char* fNetBuffer; | |||
| public: | |||
| NetMidiBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ); | |||
| ~NetMidiBuffer(); | |||
| JackMidiBuffer** fPortBuffer; | |||
| void Reset(); | |||
| size_t GetSize(); | |||
| //utility | |||
| void DisplayEvents(); | |||
| //jack<->buffer | |||
| int RenderFromJackPorts(); | |||
| int RenderToJackPorts(); | |||
| //network<->buffer | |||
| int RenderFromNetwork ( int subcycle, size_t copy_size ); | |||
| int RenderToNetwork ( int subcycle, size_t total_size ); | |||
| }; | |||
| class EXPORT NetMidiBuffer | |||
| { | |||
| private: | |||
| int fNPorts; | |||
| size_t fMaxBufsize; | |||
| int fMaxPcktSize; | |||
| //data | |||
| char* fBuffer; | |||
| char* fNetBuffer; | |||
| public: | |||
| NetMidiBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ); | |||
| ~NetMidiBuffer(); | |||
| JackMidiBuffer** fPortBuffer; | |||
| void Reset(); | |||
| size_t GetSize(); | |||
| //utility | |||
| void DisplayEvents(); | |||
| //jack<->buffer | |||
| int RenderFromJackPorts(); | |||
| int RenderToJackPorts(); | |||
| //network<->buffer | |||
| int RenderFromNetwork ( int subcycle, size_t copy_size ); | |||
| int RenderToNetwork ( int subcycle, size_t total_size ); | |||
| }; | |||
| // audio data ********************************************************************************* | |||
| class EXPORT NetAudioBuffer | |||
| { | |||
| private: | |||
| int fNPorts; | |||
| jack_nframes_t fPeriodSize; | |||
| jack_nframes_t fSubPeriodSize; | |||
| size_t fSubPeriodBytesSize; | |||
| char* fNetBuffer; | |||
| public: | |||
| NetAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ); | |||
| ~NetAudioBuffer(); | |||
| sample_t** fPortBuffer; | |||
| size_t GetSize(); | |||
| //jack<->buffer | |||
| void RenderFromJackPorts ( int subcycle ); | |||
| void RenderToJackPorts ( int subcycle ); | |||
| }; | |||
| class EXPORT NetAudioBuffer | |||
| { | |||
| private: | |||
| int fNPorts; | |||
| jack_nframes_t fPeriodSize; | |||
| jack_nframes_t fSubPeriodSize; | |||
| size_t fSubPeriodBytesSize; | |||
| char* fNetBuffer; | |||
| public: | |||
| NetAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ); | |||
| ~NetAudioBuffer(); | |||
| sample_t** fPortBuffer; | |||
| size_t GetSize(); | |||
| //jack<->buffer | |||
| void RenderFromJackPorts ( int subcycle ); | |||
| void RenderToJackPorts ( int subcycle ); | |||
| }; | |||
| //utility ************************************************************************************* | |||
| //socket API management | |||
| EXPORT int SocketAPIInit(); | |||
| EXPORT int SocketAPIEnd(); | |||
| //n<-->h functions | |||
| EXPORT void SessionParamsHToN ( session_params_t* params ); | |||
| EXPORT void SessionParamsNToH ( session_params_t* params ); | |||
| EXPORT void PacketHeaderHToN ( packet_header_t* header ); | |||
| EXPORT void PacketHeaderNToH ( packet_header_t* header ); | |||
| //display session parameters | |||
| EXPORT void SessionParamsDisplay ( session_params_t* params ); | |||
| //display packet header | |||
| EXPORT void PacketHeaderDisplay ( packet_header_t* header ); | |||
| //get the packet type from a sesion parameters | |||
| EXPORT sync_packet_type_t GetPacketType ( session_params_t* params ); | |||
| //set the packet type in a session parameters | |||
| EXPORT int SetPacketType ( session_params_t* params, sync_packet_type_t packet_type ); | |||
| //step of network initialization | |||
| EXPORT jack_nframes_t SetFramesPerPacket ( session_params_t* params ); | |||
| //get the midi packet number for a given cycle | |||
| EXPORT int GetNMidiPckt ( session_params_t* params, size_t data_size ); | |||
| //set the recv timeout on a socket | |||
| EXPORT int SetRxTimeout ( JackNetSocket* socket, session_params_t* params ); | |||
| //check if 'next' packet is really the next after 'previous' | |||
| EXPORT bool IsNextPacket ( packet_header_t* previous, packet_header_t* next, uint subcycles ); | |||
| //socket API management | |||
| EXPORT int SocketAPIInit(); | |||
| EXPORT int SocketAPIEnd(); | |||
| //n<-->h functions | |||
| EXPORT void SessionParamsHToN ( session_params_t* params ); | |||
| EXPORT void SessionParamsNToH ( session_params_t* params ); | |||
| EXPORT void PacketHeaderHToN ( packet_header_t* header ); | |||
| EXPORT void PacketHeaderNToH ( packet_header_t* header ); | |||
| //display session parameters | |||
| EXPORT void SessionParamsDisplay ( session_params_t* params ); | |||
| //display packet header | |||
| EXPORT void PacketHeaderDisplay ( packet_header_t* header ); | |||
| //get the packet type from a sesion parameters | |||
| EXPORT sync_packet_type_t GetPacketType ( session_params_t* params ); | |||
| //set the packet type in a session parameters | |||
| EXPORT int SetPacketType ( session_params_t* params, sync_packet_type_t packet_type ); | |||
| //step of network initialization | |||
| EXPORT jack_nframes_t SetFramesPerPacket ( session_params_t* params ); | |||
| //get the midi packet number for a given cycle | |||
| EXPORT int GetNMidiPckt ( session_params_t* params, size_t data_size ); | |||
| //set the recv timeout on a socket | |||
| EXPORT int SetRxTimeout ( JackNetSocket* socket, session_params_t* params ); | |||
| //check if 'next' packet is really the next after 'previous' | |||
| EXPORT bool IsNextPacket ( packet_header_t* previous, packet_header_t* next, uint subcycles ); | |||
| } | |||
| @@ -20,270 +20,270 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include "JackNetUnixSocket.h" | |||
| namespace Jack | |||
| { | |||
| //utility ********************************************************************************************************* | |||
| int GetHostName ( char * name, int size ) | |||
| { | |||
| if ( gethostname ( name, size) == SOCKET_ERROR ) | |||
| { | |||
| jack_error ( "Can't get 'hostname' : %s", strerror ( NET_ERROR_CODE ) ); | |||
| strcpy ( name, "default" ); | |||
| return -1; | |||
| } | |||
| return 0; | |||
| } | |||
| //construct/destruct*********************************************************************************************** | |||
| JackNetUnixSocket::JackNetUnixSocket() | |||
| { | |||
| fSockfd = 0; | |||
| fSendAddr.sin_family = AF_INET; | |||
| fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fSendAddr.sin_zero, 0, 8 ); | |||
| fRecvAddr.sin_family = AF_INET; | |||
| fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fRecvAddr.sin_zero, 0, 8 ); | |||
| } | |||
| JackNetUnixSocket::JackNetUnixSocket ( const char* ip, int port ) | |||
| { | |||
| fSockfd = 0; | |||
| fPort = port; | |||
| fSendAddr.sin_family = AF_INET; | |||
| fSendAddr.sin_port = htons ( port ); | |||
| inet_aton ( ip, &fSendAddr.sin_addr ); | |||
| memset ( &fSendAddr.sin_zero, 0, 8 ); | |||
| fRecvAddr.sin_family = AF_INET; | |||
| fRecvAddr.sin_port = htons ( port ); | |||
| fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fRecvAddr.sin_zero, 0, 8 ); | |||
| } | |||
| JackNetUnixSocket::~JackNetUnixSocket() | |||
| { | |||
| Close(); | |||
| } | |||
| //socket*********************************************************************************************************** | |||
| int JackNetUnixSocket::NewSocket() | |||
| { | |||
| if ( fSockfd ) | |||
| { | |||
| Close(); | |||
| Reset(); | |||
| } | |||
| fSockfd = socket ( AF_INET, SOCK_DGRAM, 0 ); | |||
| return fSockfd; | |||
| } | |||
| int JackNetUnixSocket::Bind() | |||
| { | |||
| return bind ( fSockfd, reinterpret_cast<socket_address_t*> ( &fRecvAddr ), sizeof ( socket_address_t ) ); | |||
| } | |||
| int JackNetUnixSocket::BindWith ( const char* ip ) | |||
| { | |||
| int addr_conv = inet_aton ( ip, &fRecvAddr.sin_addr ); | |||
| if ( addr_conv < 0 ) | |||
| return addr_conv; | |||
| return Bind(); | |||
| } | |||
| int JackNetUnixSocket::BindWith ( int port ) | |||
| { | |||
| fRecvAddr.sin_port = htons ( port ); | |||
| return Bind(); | |||
| } | |||
| int JackNetUnixSocket::Connect() | |||
| { | |||
| return connect ( fSockfd, reinterpret_cast<socket_address_t*> ( &fSendAddr ), sizeof ( socket_address_t ) ); | |||
| } | |||
| int JackNetUnixSocket::ConnectTo ( const char* ip ) | |||
| { | |||
| int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr ); | |||
| if ( addr_conv < 0 ) | |||
| return addr_conv; | |||
| return Connect(); | |||
| } | |||
| void JackNetUnixSocket::Close() | |||
| { | |||
| if ( fSockfd ) | |||
| close ( fSockfd ); | |||
| fSockfd = 0; | |||
| } | |||
| void JackNetUnixSocket::Reset() | |||
| { | |||
| fSendAddr.sin_family = AF_INET; | |||
| fSendAddr.sin_port = htons ( fPort ); | |||
| fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fSendAddr.sin_zero, 0, 8 ); | |||
| fRecvAddr.sin_family = AF_INET; | |||
| fRecvAddr.sin_port = htons ( fPort ); | |||
| fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fRecvAddr.sin_zero, 0, 8 ); | |||
| } | |||
| bool JackNetUnixSocket::IsSocket() | |||
| { | |||
| return ( fSockfd ) ? true : false; | |||
| } | |||
| //IP/PORT*********************************************************************************************************** | |||
| void JackNetUnixSocket::SetPort ( int port ) | |||
| { | |||
| fPort = port; | |||
| fSendAddr.sin_port = htons ( port ); | |||
| fRecvAddr.sin_port = htons ( port ); | |||
| } | |||
| int JackNetUnixSocket::GetPort() | |||
| { | |||
| return fPort; | |||
| } | |||
| //address*********************************************************************************************************** | |||
| int JackNetUnixSocket::SetAddress ( const char* ip, int port ) | |||
| { | |||
| int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr ); | |||
| if ( addr_conv < 0 ) | |||
| return addr_conv; | |||
| fSendAddr.sin_port = htons ( port ); | |||
| return 0; | |||
| } | |||
| char* JackNetUnixSocket::GetSendIP() | |||
| { | |||
| return inet_ntoa ( fSendAddr.sin_addr ); | |||
| } | |||
| char* JackNetUnixSocket::GetRecvIP() | |||
| { | |||
| return inet_ntoa ( fRecvAddr.sin_addr ); | |||
| } | |||
| //utility************************************************************************************************************ | |||
| int JackNetUnixSocket::GetName ( char* name ) | |||
| { | |||
| return gethostname ( name, 255 ); | |||
| } | |||
| int JackNetUnixSocket::JoinMCastGroup ( const char* ip ) | |||
| { | |||
| struct ip_mreq multicast_req; | |||
| inet_aton ( ip, &multicast_req.imr_multiaddr ); | |||
| multicast_req.imr_interface.s_addr = htonl ( INADDR_ANY ); | |||
| return SetOption ( IPPROTO_IP, IP_ADD_MEMBERSHIP, &multicast_req, sizeof ( multicast_req ) ); | |||
| } | |||
| void JackNetUnixSocket::CopyParams ( JackNetUnixSocket* socket ) | |||
| { | |||
| fPort = socket->fPort; | |||
| fSendAddr = socket->fSendAddr; | |||
| fRecvAddr = socket->fRecvAddr; | |||
| } | |||
| //options************************************************************************************************************ | |||
| int JackNetUnixSocket::SetOption ( int level, int optname, const void* optval, socklen_t optlen ) | |||
| { | |||
| return setsockopt ( fSockfd, level, optname, optval, optlen ); | |||
| } | |||
| int JackNetUnixSocket::GetOption ( int level, int optname, void* optval, socklen_t* optlen ) | |||
| { | |||
| return getsockopt ( fSockfd, level, optname, optval, optlen ); | |||
| } | |||
| //timeout************************************************************************************************************* | |||
| int JackNetUnixSocket::SetTimeOut ( int& msec ) | |||
| { | |||
| //negative timeout, or exceeding 10s, return | |||
| if ( ( msec < 0 ) || ( msec > 10000 ) ) | |||
| return -1; | |||
| struct timeval timeout; | |||
| //less than 1sec | |||
| if ( msec < 1000 ) | |||
| { | |||
| timeout.tv_sec = 0; | |||
| timeout.tv_usec = msec * 1000; | |||
| return SetOption ( SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof ( timeout ) ); | |||
| } | |||
| //more than 1sec | |||
| if ( msec >= 1000 ) | |||
| { | |||
| float sec = static_cast<float>( msec ) / 1000.0f; | |||
| timeout.tv_sec = ( int ) sec; | |||
| float usec = ( sec - timeout.tv_sec ) * 1000000; | |||
| timeout.tv_usec = ( int ) usec; | |||
| return SetOption ( SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof ( timeout ) ); | |||
| } | |||
| return -1; | |||
| } | |||
| //local loop********************************************************************************************************** | |||
| int JackNetUnixSocket::SetLocalLoop() | |||
| { | |||
| char disable = 0; | |||
| return SetOption ( IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof ( disable ) ); | |||
| } | |||
| //network operations************************************************************************************************** | |||
| int JackNetUnixSocket::SendTo ( const void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| return sendto ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fSendAddr ), sizeof ( socket_address_t ) ); | |||
| } | |||
| int JackNetUnixSocket::SendTo ( const void* buffer, size_t nbytes, int flags, const char* ip ) | |||
| { | |||
| int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr ); | |||
| if ( addr_conv < 1 ) | |||
| return addr_conv; | |||
| return SendTo ( buffer, nbytes, flags ); | |||
| } | |||
| int JackNetUnixSocket::Send ( const void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| return send ( fSockfd, buffer, nbytes, flags ); | |||
| } | |||
| int JackNetUnixSocket::RecvFrom ( void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| socklen_t addr_len = sizeof ( socket_address_t ); | |||
| return recvfrom ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fRecvAddr ), &addr_len ); | |||
| } | |||
| int JackNetUnixSocket::Recv ( void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| return recv ( fSockfd, buffer, nbytes, flags ); | |||
| } | |||
| int JackNetUnixSocket::CatchHost ( void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| socklen_t addr_len = sizeof ( socket_address_t ); | |||
| return recvfrom ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fSendAddr ), &addr_len ); | |||
| } | |||
| net_error_t JackNetUnixSocket::GetError() | |||
| { | |||
| switch ( errno ) | |||
| { | |||
| case EAGAIN: | |||
| return NET_NO_DATA; | |||
| case ECONNABORTED: | |||
| return NET_CONN_ERROR; | |||
| case ECONNREFUSED: | |||
| return NET_CONN_ERROR; | |||
| case ECONNRESET: | |||
| return NET_CONN_ERROR; | |||
| case EHOSTDOWN: | |||
| return NET_CONN_ERROR; | |||
| case EHOSTUNREACH: | |||
| return NET_CONN_ERROR; | |||
| default: | |||
| return NET_OP_ERROR; | |||
| } | |||
| } | |||
| { | |||
| //utility ********************************************************************************************************* | |||
| int GetHostName ( char * name, int size ) | |||
| { | |||
| if ( gethostname ( name, size) == SOCKET_ERROR ) | |||
| { | |||
| jack_error ( "Can't get 'hostname' : %s", strerror ( NET_ERROR_CODE ) ); | |||
| strcpy ( name, "default" ); | |||
| return -1; | |||
| } | |||
| return 0; | |||
| } | |||
| //construct/destruct*********************************************************************************************** | |||
| JackNetUnixSocket::JackNetUnixSocket() | |||
| { | |||
| fSockfd = 0; | |||
| fSendAddr.sin_family = AF_INET; | |||
| fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fSendAddr.sin_zero, 0, 8 ); | |||
| fRecvAddr.sin_family = AF_INET; | |||
| fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fRecvAddr.sin_zero, 0, 8 ); | |||
| } | |||
| JackNetUnixSocket::JackNetUnixSocket ( const char* ip, int port ) | |||
| { | |||
| fSockfd = 0; | |||
| fPort = port; | |||
| fSendAddr.sin_family = AF_INET; | |||
| fSendAddr.sin_port = htons ( port ); | |||
| inet_aton ( ip, &fSendAddr.sin_addr ); | |||
| memset ( &fSendAddr.sin_zero, 0, 8 ); | |||
| fRecvAddr.sin_family = AF_INET; | |||
| fRecvAddr.sin_port = htons ( port ); | |||
| fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fRecvAddr.sin_zero, 0, 8 ); | |||
| } | |||
| JackNetUnixSocket::~JackNetUnixSocket() | |||
| { | |||
| Close(); | |||
| } | |||
| //socket*********************************************************************************************************** | |||
| int JackNetUnixSocket::NewSocket() | |||
| { | |||
| if ( fSockfd ) | |||
| { | |||
| Close(); | |||
| Reset(); | |||
| } | |||
| fSockfd = socket ( AF_INET, SOCK_DGRAM, 0 ); | |||
| return fSockfd; | |||
| } | |||
| int JackNetUnixSocket::Bind() | |||
| { | |||
| return bind ( fSockfd, reinterpret_cast<socket_address_t*> ( &fRecvAddr ), sizeof ( socket_address_t ) ); | |||
| } | |||
| int JackNetUnixSocket::BindWith ( const char* ip ) | |||
| { | |||
| int addr_conv = inet_aton ( ip, &fRecvAddr.sin_addr ); | |||
| if ( addr_conv < 0 ) | |||
| return addr_conv; | |||
| return Bind(); | |||
| } | |||
| int JackNetUnixSocket::BindWith ( int port ) | |||
| { | |||
| fRecvAddr.sin_port = htons ( port ); | |||
| return Bind(); | |||
| } | |||
| int JackNetUnixSocket::Connect() | |||
| { | |||
| return connect ( fSockfd, reinterpret_cast<socket_address_t*> ( &fSendAddr ), sizeof ( socket_address_t ) ); | |||
| } | |||
| int JackNetUnixSocket::ConnectTo ( const char* ip ) | |||
| { | |||
| int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr ); | |||
| if ( addr_conv < 0 ) | |||
| return addr_conv; | |||
| return Connect(); | |||
| } | |||
| void JackNetUnixSocket::Close() | |||
| { | |||
| if ( fSockfd ) | |||
| close ( fSockfd ); | |||
| fSockfd = 0; | |||
| } | |||
| void JackNetUnixSocket::Reset() | |||
| { | |||
| fSendAddr.sin_family = AF_INET; | |||
| fSendAddr.sin_port = htons ( fPort ); | |||
| fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fSendAddr.sin_zero, 0, 8 ); | |||
| fRecvAddr.sin_family = AF_INET; | |||
| fRecvAddr.sin_port = htons ( fPort ); | |||
| fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fRecvAddr.sin_zero, 0, 8 ); | |||
| } | |||
| bool JackNetUnixSocket::IsSocket() | |||
| { | |||
| return ( fSockfd ) ? true : false; | |||
| } | |||
| //IP/PORT*********************************************************************************************************** | |||
| void JackNetUnixSocket::SetPort ( int port ) | |||
| { | |||
| fPort = port; | |||
| fSendAddr.sin_port = htons ( port ); | |||
| fRecvAddr.sin_port = htons ( port ); | |||
| } | |||
| int JackNetUnixSocket::GetPort() | |||
| { | |||
| return fPort; | |||
| } | |||
| //address*********************************************************************************************************** | |||
| int JackNetUnixSocket::SetAddress ( const char* ip, int port ) | |||
| { | |||
| int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr ); | |||
| if ( addr_conv < 0 ) | |||
| return addr_conv; | |||
| fSendAddr.sin_port = htons ( port ); | |||
| return 0; | |||
| } | |||
| char* JackNetUnixSocket::GetSendIP() | |||
| { | |||
| return inet_ntoa ( fSendAddr.sin_addr ); | |||
| } | |||
| char* JackNetUnixSocket::GetRecvIP() | |||
| { | |||
| return inet_ntoa ( fRecvAddr.sin_addr ); | |||
| } | |||
| //utility************************************************************************************************************ | |||
| int JackNetUnixSocket::GetName ( char* name ) | |||
| { | |||
| return gethostname ( name, 255 ); | |||
| } | |||
| int JackNetUnixSocket::JoinMCastGroup ( const char* ip ) | |||
| { | |||
| struct ip_mreq multicast_req; | |||
| inet_aton ( ip, &multicast_req.imr_multiaddr ); | |||
| multicast_req.imr_interface.s_addr = htonl ( INADDR_ANY ); | |||
| return SetOption ( IPPROTO_IP, IP_ADD_MEMBERSHIP, &multicast_req, sizeof ( multicast_req ) ); | |||
| } | |||
| void JackNetUnixSocket::CopyParams ( JackNetUnixSocket* socket ) | |||
| { | |||
| fPort = socket->fPort; | |||
| fSendAddr = socket->fSendAddr; | |||
| fRecvAddr = socket->fRecvAddr; | |||
| } | |||
| //options************************************************************************************************************ | |||
| int JackNetUnixSocket::SetOption ( int level, int optname, const void* optval, socklen_t optlen ) | |||
| { | |||
| return setsockopt ( fSockfd, level, optname, optval, optlen ); | |||
| } | |||
| int JackNetUnixSocket::GetOption ( int level, int optname, void* optval, socklen_t* optlen ) | |||
| { | |||
| return getsockopt ( fSockfd, level, optname, optval, optlen ); | |||
| } | |||
| //timeout************************************************************************************************************* | |||
| int JackNetUnixSocket::SetTimeOut ( int& msec ) | |||
| { | |||
| //negative timeout, or exceeding 10s, return | |||
| if ( ( msec < 0 ) || ( msec > 10000 ) ) | |||
| return -1; | |||
| struct timeval timeout; | |||
| //less than 1sec | |||
| if ( msec < 1000 ) | |||
| { | |||
| timeout.tv_sec = 0; | |||
| timeout.tv_usec = msec * 1000; | |||
| return SetOption ( SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof ( timeout ) ); | |||
| } | |||
| //more than 1sec | |||
| if ( msec >= 1000 ) | |||
| { | |||
| float sec = static_cast<float>( msec ) / 1000.0f; | |||
| timeout.tv_sec = ( int ) sec; | |||
| float usec = ( sec - timeout.tv_sec ) * 1000000; | |||
| timeout.tv_usec = ( int ) usec; | |||
| return SetOption ( SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof ( timeout ) ); | |||
| } | |||
| return -1; | |||
| } | |||
| //local loop********************************************************************************************************** | |||
| int JackNetUnixSocket::SetLocalLoop() | |||
| { | |||
| char disable = 0; | |||
| return SetOption ( IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof ( disable ) ); | |||
| } | |||
| //network operations************************************************************************************************** | |||
| int JackNetUnixSocket::SendTo ( const void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| return sendto ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fSendAddr ), sizeof ( socket_address_t ) ); | |||
| } | |||
| int JackNetUnixSocket::SendTo ( const void* buffer, size_t nbytes, int flags, const char* ip ) | |||
| { | |||
| int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr ); | |||
| if ( addr_conv < 1 ) | |||
| return addr_conv; | |||
| return SendTo ( buffer, nbytes, flags ); | |||
| } | |||
| int JackNetUnixSocket::Send ( const void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| return send ( fSockfd, buffer, nbytes, flags ); | |||
| } | |||
| int JackNetUnixSocket::RecvFrom ( void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| socklen_t addr_len = sizeof ( socket_address_t ); | |||
| return recvfrom ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fRecvAddr ), &addr_len ); | |||
| } | |||
| int JackNetUnixSocket::Recv ( void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| return recv ( fSockfd, buffer, nbytes, flags ); | |||
| } | |||
| int JackNetUnixSocket::CatchHost ( void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| socklen_t addr_len = sizeof ( socket_address_t ); | |||
| return recvfrom ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fSendAddr ), &addr_len ); | |||
| } | |||
| net_error_t JackNetUnixSocket::GetError() | |||
| { | |||
| switch ( errno ) | |||
| { | |||
| case EAGAIN: | |||
| return NET_NO_DATA; | |||
| case ECONNABORTED: | |||
| return NET_CONN_ERROR; | |||
| case ECONNREFUSED: | |||
| return NET_CONN_ERROR; | |||
| case ECONNRESET: | |||
| return NET_CONN_ERROR; | |||
| case EHOSTDOWN: | |||
| return NET_CONN_ERROR; | |||
| case EHOSTUNREACH: | |||
| return NET_CONN_ERROR; | |||
| default: | |||
| return NET_OP_ERROR; | |||
| } | |||
| } | |||
| } | |||
| @@ -29,73 +29,73 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| namespace Jack | |||
| { | |||
| #define NET_ERROR_CODE errno | |||
| #define SOCKET_ERROR -1 | |||
| #define StrError strerror | |||
| typedef struct sockaddr socket_address_t; | |||
| typedef struct in_addr address_t; | |||
| //JackNetUnixSocket******************************************** | |||
| class EXPORT JackNetUnixSocket | |||
| { | |||
| private: | |||
| int fSockfd; | |||
| int fPort; | |||
| struct sockaddr_in fSendAddr; | |||
| struct sockaddr_in fRecvAddr; | |||
| public: | |||
| JackNetUnixSocket(); | |||
| JackNetUnixSocket ( const char* ip, int port ); | |||
| ~JackNetUnixSocket(); | |||
| //socket management | |||
| int NewSocket(); | |||
| int Bind(); | |||
| int BindWith ( const char* ip ); | |||
| int BindWith ( int port ); | |||
| int Connect(); | |||
| int ConnectTo ( const char* ip ); | |||
| void Close(); | |||
| void Reset(); | |||
| bool IsSocket(); | |||
| //IP/PORT management | |||
| void SetPort ( int port ); | |||
| int GetPort(); | |||
| //address management | |||
| int SetAddress ( const char* ip, int port ); | |||
| char* GetSendIP(); | |||
| char* GetRecvIP(); | |||
| //utility | |||
| int GetName ( char* name ); | |||
| int JoinMCastGroup ( const char* mcast_ip ); | |||
| void CopyParams ( JackNetUnixSocket* socket ); | |||
| //options management | |||
| int SetOption ( int level, int optname, const void* optval, socklen_t optlen ); | |||
| int GetOption ( int level, int optname, void* optval, socklen_t* optlen ); | |||
| //timeout | |||
| int SetTimeOut ( int& msec ); | |||
| //local loop | |||
| int SetLocalLoop(); | |||
| //network operations | |||
| int SendTo ( const void* buffer, size_t nbytes, int flags ); | |||
| int SendTo ( const void* buffer, size_t nbytes, int flags, const char* ip ); | |||
| int Send ( const void* buffer, size_t nbytes, int flags ); | |||
| int RecvFrom ( void* buffer, size_t nbytes, int flags ); | |||
| int Recv ( void* buffer, size_t nbytes, int flags ); | |||
| int CatchHost ( void* buffer, size_t nbytes, int flags ); | |||
| //error management | |||
| net_error_t GetError(); | |||
| }; | |||
| #define NET_ERROR_CODE errno | |||
| #define SOCKET_ERROR -1 | |||
| #define StrError strerror | |||
| typedef struct sockaddr socket_address_t; | |||
| typedef struct in_addr address_t; | |||
| //JackNetUnixSocket******************************************** | |||
| class EXPORT JackNetUnixSocket | |||
| { | |||
| private: | |||
| int fSockfd; | |||
| int fPort; | |||
| struct sockaddr_in fSendAddr; | |||
| struct sockaddr_in fRecvAddr; | |||
| public: | |||
| JackNetUnixSocket(); | |||
| JackNetUnixSocket ( const char* ip, int port ); | |||
| ~JackNetUnixSocket(); | |||
| //socket management | |||
| int NewSocket(); | |||
| int Bind(); | |||
| int BindWith ( const char* ip ); | |||
| int BindWith ( int port ); | |||
| int Connect(); | |||
| int ConnectTo ( const char* ip ); | |||
| void Close(); | |||
| void Reset(); | |||
| bool IsSocket(); | |||
| //IP/PORT management | |||
| void SetPort ( int port ); | |||
| int GetPort(); | |||
| //address management | |||
| int SetAddress ( const char* ip, int port ); | |||
| char* GetSendIP(); | |||
| char* GetRecvIP(); | |||
| //utility | |||
| int GetName ( char* name ); | |||
| int JoinMCastGroup ( const char* mcast_ip ); | |||
| void CopyParams ( JackNetUnixSocket* socket ); | |||
| //options management | |||
| int SetOption ( int level, int optname, const void* optval, socklen_t optlen ); | |||
| int GetOption ( int level, int optname, void* optval, socklen_t* optlen ); | |||
| //timeout | |||
| int SetTimeOut ( int& msec ); | |||
| //local loop | |||
| int SetLocalLoop(); | |||
| //network operations | |||
| int SendTo ( const void* buffer, size_t nbytes, int flags ); | |||
| int SendTo ( const void* buffer, size_t nbytes, int flags, const char* ip ); | |||
| int Send ( const void* buffer, size_t nbytes, int flags ); | |||
| int RecvFrom ( void* buffer, size_t nbytes, int flags ); | |||
| int Recv ( void* buffer, size_t nbytes, int flags ); | |||
| int CatchHost ( void* buffer, size_t nbytes, int flags ); | |||
| //error management | |||
| net_error_t GetError(); | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -1,336 +1,340 @@ | |||
| /* | |||
| Copyright (C) 2008 Romain Moret at Grame | |||
| 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., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #include "JackNetWinSocket.h" | |||
| namespace Jack | |||
| { | |||
| //utility ********************************************************************************************************* | |||
| EXPORT int GetHostName ( char * name, int size ) | |||
| { | |||
| if ( gethostname ( name, size ) == SOCKET_ERROR ) | |||
| { | |||
| jack_error ( "Can't get 'hostname' : %s", strerror ( NET_ERROR_CODE ) ); | |||
| strcpy ( name, "default" ); | |||
| return -1; | |||
| } | |||
| return 0; | |||
| } | |||
| struct { int code; char* msg; } NetErrorList[] = | |||
| { | |||
| E(0, "No error"), | |||
| E(WSAEINTR, "Interrupted system call"), | |||
| E(WSAEBADF, "Bad file number"), | |||
| E(WSAEACCES, "Permission denied"), | |||
| E(WSAEFAULT, "Bad address"), | |||
| E(WSAEINVAL, "Invalid argument"), | |||
| E(WSAEMFILE, "Too many open sockets"), | |||
| E(WSAEWOULDBLOCK, "Operation would block"), | |||
| E(WSAEINPROGRESS, "Operation now in progress"), | |||
| E(WSAEALREADY, "Operation already in progress"), | |||
| E(WSAENOTSOCK, "Socket operation on non-socket"), | |||
| E(WSAEDESTADDRREQ, "Destination address required"), | |||
| E(WSAEMSGSIZE, "Message too long"), | |||
| E(WSAEPROTOTYPE, "Protocol wrong type for socket"), | |||
| E(WSAENOPROTOOPT, "Bad protocol option"), | |||
| E(WSAEPROTONOSUPPORT, "Protocol not supported"), | |||
| E(WSAESOCKTNOSUPPORT, "Socket type not supported"), | |||
| E(WSAEOPNOTSUPP, "Operation not supported on socket"), | |||
| E(WSAEPFNOSUPPORT, "Protocol family not supported"), | |||
| E(WSAEAFNOSUPPORT, "Address family not supported"), | |||
| E(WSAEADDRINUSE, "Address already in use"), | |||
| E(WSAEADDRNOTAVAIL, "Can't assign requested address"), | |||
| E(WSAENETDOWN, "Network is down"), | |||
| E(WSAENETUNREACH, "Network is unreachable"), | |||
| E(WSAENETRESET, "Net connection reset"), | |||
| E(WSAECONNABORTED, "Software caused connection abort"), | |||
| E(WSAECONNRESET, "Connection reset by peer"), | |||
| E(WSAENOBUFS, "No buffer space available"), | |||
| E(WSAEISCONN, "Socket is already connected"), | |||
| E(WSAENOTCONN, "Socket is not connected"), | |||
| E(WSAESHUTDOWN, "Can't send after socket shutdown"), | |||
| E(WSAETOOMANYREFS, "Too many references, can't splice"), | |||
| E(WSAETIMEDOUT, "Connection timed out"), | |||
| E(WSAECONNREFUSED, "Connection refused"), | |||
| E(WSAELOOP, "Too many levels of symbolic links"), | |||
| E(WSAENAMETOOLONG, "File name too long"), | |||
| E(WSAEHOSTDOWN, "Host is down"), | |||
| E(WSAEHOSTUNREACH, "No route to host"), | |||
| E(WSAENOTEMPTY, "Directory not empty"), | |||
| E(WSAEPROCLIM, "Too many processes"), | |||
| E(WSAEUSERS, "Too many users"), | |||
| E(WSAEDQUOT, "Disc quota exceeded"), | |||
| E(WSAESTALE, "Stale NFS file handle"), | |||
| E(WSAEREMOTE, "Too many levels of remote in path"), | |||
| E(WSASYSNOTREADY, "Network system is unavailable"), | |||
| E(WSAVERNOTSUPPORTED, "Winsock version out of range"), | |||
| E(WSANOTINITIALISED, "WSAStartup not yet called"), | |||
| E(WSAEDISCON, "Graceful shutdown in progress"), | |||
| E(WSAHOST_NOT_FOUND, "Host not found"), | |||
| E(WSANO_DATA, "No host data of that type was found"), | |||
| { -1, NULL }, | |||
| }; | |||
| EXPORT const char* PrintError ( int error ) | |||
| { | |||
| int i; | |||
| for ( i = 0; NetErrorList[i].code >= 0; ++i) | |||
| { | |||
| if ( error == NetErrorList[i].code ) | |||
| return NetErrorList[i].msg; | |||
| } | |||
| return strerror ( error ); | |||
| } | |||
| //construct/destruct*********************************************************************************************** | |||
| JackNetWinSocket::JackNetWinSocket() | |||
| { | |||
| fSockfd = 0; | |||
| fSendAddr.sin_family = AF_INET; | |||
| fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fSendAddr.sin_zero, 0, 8 ); | |||
| fRecvAddr.sin_family = AF_INET; | |||
| fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fRecvAddr.sin_zero, 0, 8 ); | |||
| } | |||
| JackNetWinSocket::JackNetWinSocket ( const char* ip, int port ) | |||
| { | |||
| fSockfd = 0; | |||
| fPort = port; | |||
| fSendAddr.sin_family = AF_INET; | |||
| fSendAddr.sin_port = htons ( port ); | |||
| fSendAddr.sin_addr.s_addr = inet_addr ( ip ); | |||
| memset ( &fSendAddr.sin_zero, 0, 8 ); | |||
| fRecvAddr.sin_family = AF_INET; | |||
| fRecvAddr.sin_port = htons ( port ); | |||
| fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fRecvAddr.sin_zero, 0, 8 ); | |||
| } | |||
| JackNetWinSocket::~JackNetWinSocket() | |||
| { | |||
| Close(); | |||
| } | |||
| //socket*********************************************************************************************************** | |||
| int JackNetWinSocket::NewSocket() | |||
| { | |||
| if ( fSockfd ) | |||
| { | |||
| Close(); | |||
| Reset(); | |||
| } | |||
| fSockfd = socket ( AF_INET, SOCK_DGRAM, 0 ); | |||
| return fSockfd; | |||
| } | |||
| int JackNetWinSocket::Bind() | |||
| { | |||
| return bind ( fSockfd, reinterpret_cast<SOCKADDR*> ( &fRecvAddr ), sizeof ( SOCKADDR ) ); | |||
| } | |||
| int JackNetWinSocket::BindWith ( const char* ip ) | |||
| { | |||
| fRecvAddr.sin_addr.s_addr = inet_addr ( ip ); | |||
| return Bind(); | |||
| } | |||
| int JackNetWinSocket::BindWith ( int port ) | |||
| { | |||
| fRecvAddr.sin_port = htons ( port ); | |||
| return Bind(); | |||
| } | |||
| int JackNetWinSocket::Connect() | |||
| { | |||
| return connect ( fSockfd, reinterpret_cast<SOCKADDR*> ( &fSendAddr ), sizeof ( SOCKADDR ) ); | |||
| } | |||
| int JackNetWinSocket::ConnectTo ( const char* ip ) | |||
| { | |||
| fSendAddr.sin_addr.s_addr = inet_addr ( ip ); | |||
| return Connect(); | |||
| } | |||
| void JackNetWinSocket::Close() | |||
| { | |||
| if ( fSockfd ) | |||
| closesocket ( fSockfd ); | |||
| fSockfd = 0; | |||
| } | |||
| void JackNetWinSocket::Reset() | |||
| { | |||
| fSendAddr.sin_family = AF_INET; | |||
| fSendAddr.sin_port = htons ( fPort ); | |||
| fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fSendAddr.sin_zero, 0, 8 ); | |||
| fRecvAddr.sin_family = AF_INET; | |||
| fRecvAddr.sin_port = htons ( fPort ); | |||
| fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fRecvAddr.sin_zero, 0, 8 ); | |||
| } | |||
| bool JackNetWinSocket::IsSocket() | |||
| { | |||
| return ( fSockfd ) ? true : false; | |||
| } | |||
| //IP/PORT*********************************************************************************************************** | |||
| void JackNetWinSocket::SetPort ( int port ) | |||
| { | |||
| fPort = port; | |||
| fSendAddr.sin_port = htons ( port ); | |||
| fRecvAddr.sin_port = htons ( port ); | |||
| } | |||
| int JackNetWinSocket::GetPort() | |||
| { | |||
| return fPort; | |||
| } | |||
| //address*********************************************************************************************************** | |||
| int JackNetWinSocket::SetAddress ( const char* ip, int port ) | |||
| { | |||
| fSendAddr.sin_addr.s_addr = inet_addr ( ip ); | |||
| fSendAddr.sin_port = htons ( port ); | |||
| return 0; | |||
| } | |||
| char* JackNetWinSocket::GetSendIP() | |||
| { | |||
| return inet_ntoa ( fSendAddr.sin_addr ); | |||
| } | |||
| char* JackNetWinSocket::GetRecvIP() | |||
| { | |||
| return inet_ntoa ( fRecvAddr.sin_addr ); | |||
| } | |||
| //utility************************************************************************************************************ | |||
| int JackNetWinSocket::GetName ( char* name ) | |||
| { | |||
| return gethostname ( name, 255 ); | |||
| } | |||
| int JackNetWinSocket::JoinMCastGroup ( const char* ip ) | |||
| { | |||
| struct ip_mreq multicast_req; | |||
| multicast_req.imr_multiaddr.s_addr = inet_addr ( ip ); | |||
| multicast_req.imr_interface.s_addr = htonl ( INADDR_ANY ); | |||
| //12 is IP_ADD_MEMBERSHIP in winsock2 (differs from winsock1...) | |||
| return SetOption ( IPPROTO_IP, 12, &multicast_req, sizeof ( multicast_req ) ); | |||
| } | |||
| void JackNetWinSocket::CopyParams ( JackNetWinSocket* socket ) | |||
| { | |||
| fPort = socket->fPort; | |||
| fSendAddr = socket->fSendAddr; | |||
| fRecvAddr = socket->fRecvAddr; | |||
| } | |||
| //options************************************************************************************************************ | |||
| int JackNetWinSocket::SetOption ( int level, int optname, const void* optval, SOCKLEN optlen ) | |||
| { | |||
| return setsockopt ( fSockfd, level, optname, static_cast<const char*>(optval), optlen ); | |||
| } | |||
| int JackNetWinSocket::GetOption ( int level, int optname, void* optval, SOCKLEN* optlen ) | |||
| { | |||
| return getsockopt ( fSockfd, level, optname, static_cast<char*>(optval), optlen ); | |||
| } | |||
| //tiemout************************************************************************************************************ | |||
| int JackNetWinSocket::SetTimeOut ( int& msec ) | |||
| { | |||
| //negative timeout, or exceeding 10s, return | |||
| if ( ( msec < 0 ) || ( msec > 10000 ) ) | |||
| return -1; | |||
| return SetOption ( SOL_SOCKET, SO_RCVTIMEO, &msec, sizeof ( msec ) ); | |||
| } | |||
| //local loop********************************************************************************************************* | |||
| int JackNetWinSocket::SetLocalLoop() | |||
| { | |||
| char enable = 1; | |||
| return SetOption ( IPPROTO_IP, IP_MULTICAST_LOOP, &enable, sizeof ( enable ) ); | |||
| } | |||
| //network operations************************************************************************************************* | |||
| int JackNetWinSocket::SendTo ( const void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| return sendto ( fSockfd, reinterpret_cast<const char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*> ( &fSendAddr ), sizeof ( SOCKADDR ) ); | |||
| } | |||
| int JackNetWinSocket::SendTo ( const void* buffer, size_t nbytes, int flags, const char* ip ) | |||
| { | |||
| fSendAddr.sin_addr.s_addr = inet_addr ( ip ); | |||
| return SendTo ( buffer, nbytes, flags ); | |||
| } | |||
| int JackNetWinSocket::Send ( const void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| return send ( fSockfd, reinterpret_cast<const char*>(buffer), nbytes, flags ); | |||
| } | |||
| int JackNetWinSocket::RecvFrom ( void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| SOCKLEN addr_len = sizeof ( SOCKADDR ); | |||
| return recvfrom ( fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*> ( &fRecvAddr ), &addr_len ); | |||
| } | |||
| int JackNetWinSocket::Recv ( void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| return recv ( fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags ); | |||
| } | |||
| int JackNetWinSocket::CatchHost ( void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| SOCKLEN addr_len = sizeof ( SOCKADDR ); | |||
| return recvfrom ( fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*> ( &fSendAddr ), &addr_len ); | |||
| } | |||
| net_error_t JackNetWinSocket::GetError() | |||
| { | |||
| switch ( NET_ERROR_CODE ) | |||
| { | |||
| case WSABASEERR: | |||
| return NET_NO_ERROR; | |||
| case WSAETIMEDOUT: | |||
| return NET_NO_DATA; | |||
| case WSAECONNREFUSED: | |||
| return NET_CONN_ERROR; | |||
| case WSAECONNRESET: | |||
| return NET_CONN_ERROR; | |||
| case WSAEACCES: | |||
| return NET_CONN_ERROR; | |||
| case WSAECONNABORTED: | |||
| return NET_CONN_ERROR; | |||
| case WSAEHOSTDOWN: | |||
| return NET_CONN_ERROR; | |||
| case WSAEHOSTUNREACH: | |||
| return NET_CONN_ERROR; | |||
| default: | |||
| return NET_OP_ERROR; | |||
| } | |||
| } | |||
| } | |||
| /* | |||
| Copyright (C) 2008 Romain Moret at Grame | |||
| 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., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #include "JackNetWinSocket.h" | |||
| namespace Jack | |||
| { | |||
| //utility ********************************************************************************************************* | |||
| EXPORT int GetHostName ( char * name, int size ) | |||
| { | |||
| if ( gethostname ( name, size ) == SOCKET_ERROR ) | |||
| { | |||
| jack_error ( "Can't get 'hostname' : %s", strerror ( NET_ERROR_CODE ) ); | |||
| strcpy ( name, "default" ); | |||
| return -1; | |||
| } | |||
| return 0; | |||
| } | |||
| struct | |||
| { | |||
| int code; | |||
| char* msg; | |||
| } NetErrorList[] = | |||
| { | |||
| E(0, "No error"), | |||
| E(WSAEINTR, "Interrupted system call"), | |||
| E(WSAEBADF, "Bad file number"), | |||
| E(WSAEACCES, "Permission denied"), | |||
| E(WSAEFAULT, "Bad address"), | |||
| E(WSAEINVAL, "Invalid argument"), | |||
| E(WSAEMFILE, "Too many open sockets"), | |||
| E(WSAEWOULDBLOCK, "Operation would block"), | |||
| E(WSAEINPROGRESS, "Operation now in progress"), | |||
| E(WSAEALREADY, "Operation already in progress"), | |||
| E(WSAENOTSOCK, "Socket operation on non-socket"), | |||
| E(WSAEDESTADDRREQ, "Destination address required"), | |||
| E(WSAEMSGSIZE, "Message too long"), | |||
| E(WSAEPROTOTYPE, "Protocol wrong type for socket"), | |||
| E(WSAENOPROTOOPT, "Bad protocol option"), | |||
| E(WSAEPROTONOSUPPORT, "Protocol not supported"), | |||
| E(WSAESOCKTNOSUPPORT, "Socket type not supported"), | |||
| E(WSAEOPNOTSUPP, "Operation not supported on socket"), | |||
| E(WSAEPFNOSUPPORT, "Protocol family not supported"), | |||
| E(WSAEAFNOSUPPORT, "Address family not supported"), | |||
| E(WSAEADDRINUSE, "Address already in use"), | |||
| E(WSAEADDRNOTAVAIL, "Can't assign requested address"), | |||
| E(WSAENETDOWN, "Network is down"), | |||
| E(WSAENETUNREACH, "Network is unreachable"), | |||
| E(WSAENETRESET, "Net connection reset"), | |||
| E(WSAECONNABORTED, "Software caused connection abort"), | |||
| E(WSAECONNRESET, "Connection reset by peer"), | |||
| E(WSAENOBUFS, "No buffer space available"), | |||
| E(WSAEISCONN, "Socket is already connected"), | |||
| E(WSAENOTCONN, "Socket is not connected"), | |||
| E(WSAESHUTDOWN, "Can't send after socket shutdown"), | |||
| E(WSAETOOMANYREFS, "Too many references, can't splice"), | |||
| E(WSAETIMEDOUT, "Connection timed out"), | |||
| E(WSAECONNREFUSED, "Connection refused"), | |||
| E(WSAELOOP, "Too many levels of symbolic links"), | |||
| E(WSAENAMETOOLONG, "File name too long"), | |||
| E(WSAEHOSTDOWN, "Host is down"), | |||
| E(WSAEHOSTUNREACH, "No route to host"), | |||
| E(WSAENOTEMPTY, "Directory not empty"), | |||
| E(WSAEPROCLIM, "Too many processes"), | |||
| E(WSAEUSERS, "Too many users"), | |||
| E(WSAEDQUOT, "Disc quota exceeded"), | |||
| E(WSAESTALE, "Stale NFS file handle"), | |||
| E(WSAEREMOTE, "Too many levels of remote in path"), | |||
| E(WSASYSNOTREADY, "Network system is unavailable"), | |||
| E(WSAVERNOTSUPPORTED, "Winsock version out of range"), | |||
| E(WSANOTINITIALISED, "WSAStartup not yet called"), | |||
| E(WSAEDISCON, "Graceful shutdown in progress"), | |||
| E(WSAHOST_NOT_FOUND, "Host not found"), | |||
| E(WSANO_DATA, "No host data of that type was found"), | |||
| { -1, NULL }, | |||
| }; | |||
| EXPORT const char* PrintError ( int error ) | |||
| { | |||
| int i; | |||
| for ( i = 0; NetErrorList[i].code >= 0; ++i) | |||
| { | |||
| if ( error == NetErrorList[i].code ) | |||
| return NetErrorList[i].msg; | |||
| } | |||
| return strerror ( error ); | |||
| } | |||
| //construct/destruct*********************************************************************************************** | |||
| JackNetWinSocket::JackNetWinSocket() | |||
| { | |||
| fSockfd = 0; | |||
| fSendAddr.sin_family = AF_INET; | |||
| fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fSendAddr.sin_zero, 0, 8 ); | |||
| fRecvAddr.sin_family = AF_INET; | |||
| fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fRecvAddr.sin_zero, 0, 8 ); | |||
| } | |||
| JackNetWinSocket::JackNetWinSocket ( const char* ip, int port ) | |||
| { | |||
| fSockfd = 0; | |||
| fPort = port; | |||
| fSendAddr.sin_family = AF_INET; | |||
| fSendAddr.sin_port = htons ( port ); | |||
| fSendAddr.sin_addr.s_addr = inet_addr ( ip ); | |||
| memset ( &fSendAddr.sin_zero, 0, 8 ); | |||
| fRecvAddr.sin_family = AF_INET; | |||
| fRecvAddr.sin_port = htons ( port ); | |||
| fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fRecvAddr.sin_zero, 0, 8 ); | |||
| } | |||
| JackNetWinSocket::~JackNetWinSocket() | |||
| { | |||
| Close(); | |||
| } | |||
| //socket*********************************************************************************************************** | |||
| int JackNetWinSocket::NewSocket() | |||
| { | |||
| if ( fSockfd ) | |||
| { | |||
| Close(); | |||
| Reset(); | |||
| } | |||
| fSockfd = socket ( AF_INET, SOCK_DGRAM, 0 ); | |||
| return fSockfd; | |||
| } | |||
| int JackNetWinSocket::Bind() | |||
| { | |||
| return bind ( fSockfd, reinterpret_cast<SOCKADDR*> ( &fRecvAddr ), sizeof ( SOCKADDR ) ); | |||
| } | |||
| int JackNetWinSocket::BindWith ( const char* ip ) | |||
| { | |||
| fRecvAddr.sin_addr.s_addr = inet_addr ( ip ); | |||
| return Bind(); | |||
| } | |||
| int JackNetWinSocket::BindWith ( int port ) | |||
| { | |||
| fRecvAddr.sin_port = htons ( port ); | |||
| return Bind(); | |||
| } | |||
| int JackNetWinSocket::Connect() | |||
| { | |||
| return connect ( fSockfd, reinterpret_cast<SOCKADDR*> ( &fSendAddr ), sizeof ( SOCKADDR ) ); | |||
| } | |||
| int JackNetWinSocket::ConnectTo ( const char* ip ) | |||
| { | |||
| fSendAddr.sin_addr.s_addr = inet_addr ( ip ); | |||
| return Connect(); | |||
| } | |||
| void JackNetWinSocket::Close() | |||
| { | |||
| if ( fSockfd ) | |||
| closesocket ( fSockfd ); | |||
| fSockfd = 0; | |||
| } | |||
| void JackNetWinSocket::Reset() | |||
| { | |||
| fSendAddr.sin_family = AF_INET; | |||
| fSendAddr.sin_port = htons ( fPort ); | |||
| fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fSendAddr.sin_zero, 0, 8 ); | |||
| fRecvAddr.sin_family = AF_INET; | |||
| fRecvAddr.sin_port = htons ( fPort ); | |||
| fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||
| memset ( &fRecvAddr.sin_zero, 0, 8 ); | |||
| } | |||
| bool JackNetWinSocket::IsSocket() | |||
| { | |||
| return ( fSockfd ) ? true : false; | |||
| } | |||
| //IP/PORT*********************************************************************************************************** | |||
| void JackNetWinSocket::SetPort ( int port ) | |||
| { | |||
| fPort = port; | |||
| fSendAddr.sin_port = htons ( port ); | |||
| fRecvAddr.sin_port = htons ( port ); | |||
| } | |||
| int JackNetWinSocket::GetPort() | |||
| { | |||
| return fPort; | |||
| } | |||
| //address*********************************************************************************************************** | |||
| int JackNetWinSocket::SetAddress ( const char* ip, int port ) | |||
| { | |||
| fSendAddr.sin_addr.s_addr = inet_addr ( ip ); | |||
| fSendAddr.sin_port = htons ( port ); | |||
| return 0; | |||
| } | |||
| char* JackNetWinSocket::GetSendIP() | |||
| { | |||
| return inet_ntoa ( fSendAddr.sin_addr ); | |||
| } | |||
| char* JackNetWinSocket::GetRecvIP() | |||
| { | |||
| return inet_ntoa ( fRecvAddr.sin_addr ); | |||
| } | |||
| //utility************************************************************************************************************ | |||
| int JackNetWinSocket::GetName ( char* name ) | |||
| { | |||
| return gethostname ( name, 255 ); | |||
| } | |||
| int JackNetWinSocket::JoinMCastGroup ( const char* ip ) | |||
| { | |||
| struct ip_mreq multicast_req; | |||
| multicast_req.imr_multiaddr.s_addr = inet_addr ( ip ); | |||
| multicast_req.imr_interface.s_addr = htonl ( INADDR_ANY ); | |||
| //12 is IP_ADD_MEMBERSHIP in winsock2 (differs from winsock1...) | |||
| return SetOption ( IPPROTO_IP, 12, &multicast_req, sizeof ( multicast_req ) ); | |||
| } | |||
| void JackNetWinSocket::CopyParams ( JackNetWinSocket* socket ) | |||
| { | |||
| fPort = socket->fPort; | |||
| fSendAddr = socket->fSendAddr; | |||
| fRecvAddr = socket->fRecvAddr; | |||
| } | |||
| //options************************************************************************************************************ | |||
| int JackNetWinSocket::SetOption ( int level, int optname, const void* optval, SOCKLEN optlen ) | |||
| { | |||
| return setsockopt ( fSockfd, level, optname, static_cast<const char*>(optval), optlen ); | |||
| } | |||
| int JackNetWinSocket::GetOption ( int level, int optname, void* optval, SOCKLEN* optlen ) | |||
| { | |||
| return getsockopt ( fSockfd, level, optname, static_cast<char*>(optval), optlen ); | |||
| } | |||
| //tiemout************************************************************************************************************ | |||
| int JackNetWinSocket::SetTimeOut ( int& msec ) | |||
| { | |||
| //negative timeout, or exceeding 10s, return | |||
| if ( ( msec < 0 ) || ( msec > 10000 ) ) | |||
| return -1; | |||
| return SetOption ( SOL_SOCKET, SO_RCVTIMEO, &msec, sizeof ( msec ) ); | |||
| } | |||
| //local loop********************************************************************************************************* | |||
| int JackNetWinSocket::SetLocalLoop() | |||
| { | |||
| char enable = 1; | |||
| return SetOption ( IPPROTO_IP, IP_MULTICAST_LOOP, &enable, sizeof ( enable ) ); | |||
| } | |||
| //network operations************************************************************************************************* | |||
| int JackNetWinSocket::SendTo ( const void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| return sendto ( fSockfd, reinterpret_cast<const char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*> ( &fSendAddr ), sizeof ( SOCKADDR ) ); | |||
| } | |||
| int JackNetWinSocket::SendTo ( const void* buffer, size_t nbytes, int flags, const char* ip ) | |||
| { | |||
| fSendAddr.sin_addr.s_addr = inet_addr ( ip ); | |||
| return SendTo ( buffer, nbytes, flags ); | |||
| } | |||
| int JackNetWinSocket::Send ( const void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| return send ( fSockfd, reinterpret_cast<const char*>(buffer), nbytes, flags ); | |||
| } | |||
| int JackNetWinSocket::RecvFrom ( void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| SOCKLEN addr_len = sizeof ( SOCKADDR ); | |||
| return recvfrom ( fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*> ( &fRecvAddr ), &addr_len ); | |||
| } | |||
| int JackNetWinSocket::Recv ( void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| return recv ( fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags ); | |||
| } | |||
| int JackNetWinSocket::CatchHost ( void* buffer, size_t nbytes, int flags ) | |||
| { | |||
| SOCKLEN addr_len = sizeof ( SOCKADDR ); | |||
| return recvfrom ( fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*> ( &fSendAddr ), &addr_len ); | |||
| } | |||
| net_error_t JackNetWinSocket::GetError() | |||
| { | |||
| switch ( NET_ERROR_CODE ) | |||
| { | |||
| case WSABASEERR: | |||
| return NET_NO_ERROR; | |||
| case WSAETIMEDOUT: | |||
| return NET_NO_DATA; | |||
| case WSAECONNREFUSED: | |||
| return NET_CONN_ERROR; | |||
| case WSAECONNRESET: | |||
| return NET_CONN_ERROR; | |||
| case WSAEACCES: | |||
| return NET_CONN_ERROR; | |||
| case WSAECONNABORTED: | |||
| return NET_CONN_ERROR; | |||
| case WSAEHOSTDOWN: | |||
| return NET_CONN_ERROR; | |||
| case WSAEHOSTUNREACH: | |||
| return NET_CONN_ERROR; | |||
| default: | |||
| return NET_OP_ERROR; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,102 +1,102 @@ | |||
| /* | |||
| Copyright (C) 2008 Romain Moret at Grame | |||
| 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., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #ifndef __JackNetWinSocket__ | |||
| #define __JackNetWinSocket__ | |||
| #include "JackNetSocket.h" | |||
| #ifdef __MINGW32__ | |||
| #include <winsock2.h> | |||
| #include <ws2tcpip.h> | |||
| #endif | |||
| namespace Jack | |||
| { | |||
| #define E(code, s) { code, s } | |||
| #define NET_ERROR_CODE WSAGetLastError() | |||
| #define StrError PrintError | |||
| typedef uint32_t uint; | |||
| typedef int SOCKLEN; | |||
| EXPORT const char* PrintError ( int error ); | |||
| //JeckNetWinSocket*************************************************************************** | |||
| class EXPORT JackNetWinSocket | |||
| { | |||
| private: | |||
| int fSockfd; | |||
| int fPort; | |||
| SOCKADDR_IN fSendAddr; | |||
| SOCKADDR_IN fRecvAddr; | |||
| public: | |||
| JackNetWinSocket(); | |||
| JackNetWinSocket ( const char* ip, int port ); | |||
| ~JackNetWinSocket(); | |||
| //socket management | |||
| int NewSocket(); | |||
| int Bind(); | |||
| int BindWith ( const char* ip ); | |||
| int BindWith ( int port ); | |||
| int Connect(); | |||
| int ConnectTo ( const char* ip ); | |||
| void Close(); | |||
| void Reset(); | |||
| bool IsSocket(); | |||
| //IP/PORT management | |||
| void SetPort ( int port ); | |||
| int GetPort(); | |||
| //address management | |||
| int SetAddress ( const char* ip, int port ); | |||
| char* GetSendIP(); | |||
| char* GetRecvIP(); | |||
| //utility | |||
| int GetName ( char* name ); | |||
| int JoinMCastGroup ( const char* mcast_ip ); | |||
| void CopyParams ( JackNetWinSocket* socket ); | |||
| //options management | |||
| int SetOption ( int level, int optname, const void* optval, SOCKLEN optlen ); | |||
| int GetOption ( int level, int optname, void* optval, SOCKLEN* optlen ); | |||
| //timeout | |||
| int SetTimeOut ( int& msec ); | |||
| //local loop | |||
| int SetLocalLoop(); | |||
| //network operations | |||
| int SendTo ( const void* buffer, size_t nbytes, int flags ); | |||
| int SendTo ( const void* buffer, size_t nbytes, int flags, const char* ip ); | |||
| int Send ( const void* buffer, size_t nbytes, int flags ); | |||
| int RecvFrom ( void* buffer, size_t nbytes, int flags ); | |||
| int Recv ( void* buffer, size_t nbytes, int flags ); | |||
| int CatchHost ( void* buffer, size_t nbytes, int flags ); | |||
| //error management | |||
| net_error_t GetError(); | |||
| }; | |||
| } | |||
| #endif | |||
| /* | |||
| Copyright (C) 2008 Romain Moret at Grame | |||
| 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., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #ifndef __JackNetWinSocket__ | |||
| #define __JackNetWinSocket__ | |||
| #include "JackNetSocket.h" | |||
| #ifdef __MINGW32__ | |||
| #include <winsock2.h> | |||
| #include <ws2tcpip.h> | |||
| #endif | |||
| namespace Jack | |||
| { | |||
| #define E(code, s) { code, s } | |||
| #define NET_ERROR_CODE WSAGetLastError() | |||
| #define StrError PrintError | |||
| typedef uint32_t uint; | |||
| typedef int SOCKLEN; | |||
| EXPORT const char* PrintError ( int error ); | |||
| //JeckNetWinSocket*************************************************************************** | |||
| class EXPORT JackNetWinSocket | |||
| { | |||
| private: | |||
| int fSockfd; | |||
| int fPort; | |||
| SOCKADDR_IN fSendAddr; | |||
| SOCKADDR_IN fRecvAddr; | |||
| public: | |||
| JackNetWinSocket(); | |||
| JackNetWinSocket ( const char* ip, int port ); | |||
| ~JackNetWinSocket(); | |||
| //socket management | |||
| int NewSocket(); | |||
| int Bind(); | |||
| int BindWith ( const char* ip ); | |||
| int BindWith ( int port ); | |||
| int Connect(); | |||
| int ConnectTo ( const char* ip ); | |||
| void Close(); | |||
| void Reset(); | |||
| bool IsSocket(); | |||
| //IP/PORT management | |||
| void SetPort ( int port ); | |||
| int GetPort(); | |||
| //address management | |||
| int SetAddress ( const char* ip, int port ); | |||
| char* GetSendIP(); | |||
| char* GetRecvIP(); | |||
| //utility | |||
| int GetName ( char* name ); | |||
| int JoinMCastGroup ( const char* mcast_ip ); | |||
| void CopyParams ( JackNetWinSocket* socket ); | |||
| //options management | |||
| int SetOption ( int level, int optname, const void* optval, SOCKLEN optlen ); | |||
| int GetOption ( int level, int optname, void* optval, SOCKLEN* optlen ); | |||
| //timeout | |||
| int SetTimeOut ( int& msec ); | |||
| //local loop | |||
| int SetLocalLoop(); | |||
| //network operations | |||
| int SendTo ( const void* buffer, size_t nbytes, int flags ); | |||
| int SendTo ( const void* buffer, size_t nbytes, int flags, const char* ip ); | |||
| int Send ( const void* buffer, size_t nbytes, int flags ); | |||
| int RecvFrom ( void* buffer, size_t nbytes, int flags ); | |||
| int Recv ( void* buffer, size_t nbytes, int flags ); | |||
| int CatchHost ( void* buffer, size_t nbytes, int flags ); | |||
| //error management | |||
| net_error_t GetError(); | |||
| }; | |||
| } | |||
| #endif | |||