JackNetInterface.cpp 38.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
Copyright (C) 2001 Paul Davis
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 "JackNetInterface.h"
#include "JackException.h"
22
#include "JackPlatformPlug.h"
23
#include <assert.h>
24
25
26

using namespace std;

27
28
29
30
31
32
/*  
 TODO : since midi buffers now uses up to BUFFER_SIZE_MAX frames, 
 probably also use BUFFER_SIZE_MAX in everything related to MIDI events 
 handling (see MidiBufferInit in JackMidiPort.cpp)
*/

33
34
35
36
namespace Jack
{
    // JackNetInterface*******************************************

37
38
39
40
41
42
43
44
    JackNetInterface::JackNetInterface() : fSocket()
    {
        fTxBuffer = NULL;
        fRxBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
45
46
        memset(&fSendTransportData, 0, sizeof(net_transport_data_t));
        memset(&fReturnTransportData, 0, sizeof(net_transport_data_t));
47
48
    }

moret's avatar
moret committed
49
    JackNetInterface::JackNetInterface ( const char* multicast_ip, int port ) : fSocket ( multicast_ip, port )
50
    {
51
        strcpy(fMulticastIP, multicast_ip);
52
53
54
55
56
57
        fTxBuffer = NULL;
        fRxBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
58
59
        memset(&fSendTransportData, 0, sizeof(net_transport_data_t));
        memset(&fReturnTransportData, 0, sizeof(net_transport_data_t));
60
61
    }

moret's avatar
moret committed
62
    JackNetInterface::JackNetInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip ) : fSocket ( socket )
63
    {
moret's avatar
moret committed
64
        fParams = params;
65
        strcpy(fMulticastIP, multicast_ip);
66
67
68
69
70
71
        fTxBuffer = NULL;
        fRxBuffer = NULL;
        fNetAudioCaptureBuffer = NULL;
        fNetAudioPlaybackBuffer = NULL;
        fNetMidiCaptureBuffer = NULL;
        fNetMidiPlaybackBuffer = NULL;
72
73
        memset(&fSendTransportData, 0, sizeof(net_transport_data_t));
        memset(&fReturnTransportData, 0, sizeof(net_transport_data_t));
74
75
76
77
    }

    JackNetInterface::~JackNetInterface()
    {
moret's avatar
moret committed
78
        jack_log ( "JackNetInterface::~JackNetInterface" );
moret's avatar
moret committed
79

80
81
82
83
84
85
86
87
88
        fSocket.Close();
        delete[] fTxBuffer;
        delete[] fRxBuffer;
        delete fNetAudioCaptureBuffer;
        delete fNetAudioPlaybackBuffer;
        delete fNetMidiCaptureBuffer;
        delete fNetMidiPlaybackBuffer;
    }

89
    void JackNetInterface::SetFramesPerPacket()
moret's avatar
moret committed
90
    {
moret's avatar
moret committed
91
        jack_log ( "JackNetInterface::SetFramesPerPacket" );
moret's avatar
moret committed
92

93
94
95
96
97
98
99
        if (fParams.fSendAudioChannels == 0 && fParams.fReturnAudioChannels == 0) {
            fParams.fFramesPerPacket = fParams.fPeriodSize;
        } else {
            jack_nframes_t period = ( int ) powf ( 2.f, ( int ) ( log (float ( fParams.fMtu - sizeof ( packet_header_t ) )
                                               / ( max ( fParams.fReturnAudioChannels, fParams.fSendAudioChannels ) * sizeof ( sample_t ) ) ) / log ( 2. ) ) );
            fParams.fFramesPerPacket = ( period > fParams.fPeriodSize ) ? fParams.fPeriodSize : period;
        }
moret's avatar
moret committed
100
101
102
103
    }

    int JackNetInterface::SetNetBufferSize()
    {
moret's avatar
moret committed
104
        jack_log ( "JackNetInterface::SetNetBufferSize" );
moret's avatar
moret committed
105

moret's avatar
moret committed
106
        float audio_size, midi_size;
107
        int bufsize;
moret's avatar
moret committed
108
109
110
111
        //audio
        audio_size = fParams.fMtu * ( fParams.fPeriodSize / fParams.fFramesPerPacket );
        //midi
        midi_size = fParams.fMtu * ( max ( fParams.fSendMidiChannels, fParams.fReturnMidiChannels ) *
moret's avatar
moret committed
112
                                     fParams.fPeriodSize * sizeof ( sample_t ) / ( fParams.fMtu - sizeof ( packet_header_t ) ) );
moret's avatar
moret committed
113
        //bufsize = sync + audio + midi
114
        bufsize = MAX_LATENCY * (fParams.fMtu + ( int ) audio_size + ( int ) midi_size);
moret's avatar
moret committed
115
116
117

        //tx buffer
        if ( fSocket.SetOption ( SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR )
118
            return SOCKET_ERROR;
moret's avatar
moret committed
119
120
121

        //rx buffer
        if ( fSocket.SetOption ( SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR )
122
            return SOCKET_ERROR;
moret's avatar
moret committed
123

124
        return 0;
moret's avatar
moret committed
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
    }

    int JackNetInterface::GetNMidiPckt()
    {
        //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 ( fTxHeader.fMidiDataSize <= ( fParams.fMtu - sizeof ( packet_header_t ) ) )
            return 1;
        //else, get the number of needed packets (simply slice the biiig buffer)
        int npckt = fTxHeader.fMidiDataSize / ( fParams.fMtu - sizeof ( packet_header_t ) );
        if ( fTxHeader.fMidiDataSize % ( fParams.fMtu - sizeof ( packet_header_t ) ) )
            return ++npckt;
        return npckt;
    }

    bool JackNetInterface::IsNextPacket()
    {
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
        //ignore first cycle
144
        if ( fRxHeader.fCycle <= 1 ) {
moret's avatar
moret committed
145
            return true;
146
        }
moret's avatar
moret committed
147
        //same PcktID (cycle), next SubPcktID (subcycle)
148
149
150
        if ( ( fRxHeader.fSubCycle < ( fNSubProcess - 1 ) ) && ( rx_head->fCycle == fRxHeader.fCycle ) && ( rx_head->fSubCycle == ( fRxHeader.fSubCycle + 1 ) ) ) {
             return true;
        }
moret's avatar
moret committed
151
        //next PcktID (cycle), SubPcktID reset to 0 (first subcyle)
152
        if ( ( rx_head->fCycle == ( fRxHeader.fCycle + 1 ) ) && ( fRxHeader.fSubCycle == ( fNSubProcess - 1 ) ) && ( rx_head->fSubCycle == 0 ) ) {
moret's avatar
moret committed
153
            return true;
154
        }
moret's avatar
moret committed
155
        //else, packet(s) missing, return false
moret's avatar
moret committed
156
157
158
        return false;
    }

159
160
    void JackNetInterface::SetParams()
    {
moret's avatar
moret committed
161
        //number of audio subcycles (packets)
162
163
        fNSubProcess = fParams.fPeriodSize / fParams.fFramesPerPacket;

moret's avatar
moret committed
164
165
166
        //payload size
        fPayloadSize = fParams.fMtu - sizeof ( packet_header_t );

167
168
169
170
171
172
173
        //TX header init
        strcpy ( fTxHeader.fPacketType, "header" );
        fTxHeader.fID = fParams.fID;
        fTxHeader.fCycle = 0;
        fTxHeader.fSubCycle = 0;
        fTxHeader.fMidiDataSize = 0;
        fTxHeader.fBitdepth = fParams.fBitdepth;
moret's avatar
moret committed
174
        fTxHeader.fIsLastPckt = 0;
175
176
177
178
179
180
181
182

        //RX header init
        strcpy ( fRxHeader.fPacketType, "header" );
        fRxHeader.fID = fParams.fID;
        fRxHeader.fCycle = 0;
        fRxHeader.fSubCycle = 0;
        fRxHeader.fMidiDataSize = 0;
        fRxHeader.fBitdepth = fParams.fBitdepth;
moret's avatar
moret committed
183
        fRxHeader.fIsLastPckt = 0;
184
185
186
187

        //network buffers
        fTxBuffer = new char[fParams.fMtu];
        fRxBuffer = new char[fParams.fMtu];
188
189
        assert ( fTxBuffer );
        assert ( fRxBuffer );
190

moret's avatar
moret committed
191
        //net audio/midi buffers'addresses
192
193
194
195
        fTxData = fTxBuffer + sizeof ( packet_header_t );
        fRxData = fRxBuffer + sizeof ( packet_header_t );
    }

196
    // JackNetMasterInterface ************************************************************************************
197

198
    bool JackNetMasterInterface::Init()
199
    {
200
        jack_log ( "JackNetMasterInterface::Init, ID %u.", fParams.fID );
201

202
        session_params_t host_params;
203
        uint attempt = 0;
204
205
206
207
208
        int rx_bytes = 0;

        //socket
        if ( fSocket.NewSocket() == SOCKET_ERROR )
        {
209
210
            jack_error ( "Can't create socket : %s", StrError ( NET_ERROR_CODE ) );
            return false;
211
212
        }

213
        //timeout on receive (for init)
214
        if ( fSocket.SetTimeOut ( MASTER_INIT_TIMEOUT ) < 0 )
215
            jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );
216
            
217
218
219
220
221
222
        //connect
        if ( fSocket.Connect() == SOCKET_ERROR )
        {
            jack_error ( "Can't connect : %s", StrError ( NET_ERROR_CODE ) );
            return false;
        }
223

moret's avatar
moret committed
224
        //set the number of complete audio frames we can put in a packet
moret's avatar
moret committed
225
226
        SetFramesPerPacket();

227
228
        //send 'SLAVE_SETUP' until 'START_MASTER' received
        jack_info ( "Sending parameters to %s ...", fParams.fSlaveNetName );
229
230
        do
        {
231
            session_params_t net_params;
232
            SetPacketType ( &fParams, SLAVE_SETUP );
233
234
235
            SessionParamsHToN(&fParams, &net_params);
            
            if ( fSocket.Send ( &net_params, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR )
236
                jack_error ( "Error in send : ", StrError ( NET_ERROR_CODE ) );
237
238
239
                
            memset(&net_params, 0, sizeof ( session_params_t ));
            if ( ( ( rx_bytes = fSocket.Recv ( &net_params, sizeof ( session_params_t ), 0 ) ) == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
240
            {
241
242
                jack_error ( "Problem with network." );
                return false;
243
            }
244
245
            
            SessionParamsNToH(&net_params, &host_params);
246
        }
247
        while ( ( GetPacketType ( &host_params ) != START_MASTER ) && ( ++attempt < SLAVE_SETUP_RETRY ) );
248
        if ( attempt == SLAVE_SETUP_RETRY )
249
        {
250
251
            jack_error ( "Slave doesn't respond, exiting." );
            return false;
252
253
        }

254
        //set the new timeout for the socket
moret's avatar
moret committed
255
        if ( SetRxTimeout() == SOCKET_ERROR )
256
257
258
259
        {
            jack_error ( "Can't set rx timeout : %s", StrError ( NET_ERROR_CODE ) );
            return false;
        }
260

261
        //set the new rx buffer size
moret's avatar
moret committed
262
        if ( SetNetBufferSize() == SOCKET_ERROR )
263
        {
moret's avatar
moret committed
264
            jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) );
265
            return false;
266
        }
267
268

        return true;
269
270
    }

moret's avatar
moret committed
271
272
    int JackNetMasterInterface::SetRxTimeout()
    {
moret's avatar
moret committed
273
274
        jack_log ( "JackNetMasterInterface::SetRxTimeout" );

moret's avatar
moret committed
275
        float time = 0;
moret's avatar
moret committed
276
277
        //slow or normal mode, short timeout on recv (2 audio subcycles)
        if ( ( fParams.fNetworkMode == 's' ) || ( fParams.fNetworkMode == 'n' ) )
moret's avatar
moret committed
278
            time = 2000000.f * ( static_cast<float> ( fParams.fFramesPerPacket ) / static_cast<float> ( fParams.fSampleRate ) );
moret's avatar
moret committed
279
        //fast mode, wait for 75% of the entire cycle duration
moret's avatar
moret committed
280
281
282
283
284
        else if ( fParams.fNetworkMode == 'f' )
            time = 750000.f * ( static_cast<float> ( fParams.fPeriodSize ) / static_cast<float> ( fParams.fSampleRate ) );
        return fSocket.SetTimeOut ( static_cast<int> ( time ) );
    }

285
    void JackNetMasterInterface::SetParams()
moret's avatar
moret committed
286
    {
287
        jack_log ( "JackNetMasterInterface::SetParams" );
moret's avatar
moret committed
288
289
290

        JackNetInterface::SetParams();

291
292
        fTxHeader.fDataStream = 's';
        fRxHeader.fDataStream = 'r';
moret's avatar
moret committed
293
294

        //midi net buffers
295
296
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fTxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fRxData );
297
298
        assert ( fNetMidiCaptureBuffer );
        assert ( fNetMidiPlaybackBuffer );
moret's avatar
moret committed
299
300

        //audio net buffers
301
302
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData );
303
304
        assert ( fNetAudioCaptureBuffer );
        assert ( fNetAudioPlaybackBuffer );
moret's avatar
moret committed
305
306

        //audio netbuffer length
307
308
        fAudioTxLen = sizeof ( packet_header_t ) + fNetAudioCaptureBuffer->GetSize();
        fAudioRxLen = sizeof ( packet_header_t ) + fNetAudioPlaybackBuffer->GetSize();
moret's avatar
moret committed
309
310
    }

311
    void JackNetMasterInterface::Exit()
312
    {
313
314
315
316
        jack_log ( "JackNetMasterInterface::Exit, ID %u", fParams.fID );

        //stop process
        fRunning = false;
317

318
319
320
321
        //send a 'multicast euthanasia request' - new socket is required on macosx
        jack_info ( "Exiting '%s'", fParams.fName );
        SetPacketType ( &fParams, KILL_MASTER );
        JackNetSocket mcast_socket ( fMulticastIP, fSocket.GetPort() );
322
323
324
325
        
        session_params_t net_params;
        SessionParamsHToN(&fParams, &net_params);

326
327
        if ( mcast_socket.NewSocket() == SOCKET_ERROR )
            jack_error ( "Can't create socket : %s", StrError ( NET_ERROR_CODE ) );
328
        if ( mcast_socket.SendTo ( &net_params, sizeof ( session_params_t ), 0, fMulticastIP ) == SOCKET_ERROR )
329
            jack_error ( "Can't send suicide request : %s", StrError ( NET_ERROR_CODE ) );
330
            
331
332
333
        mcast_socket.Close();
    }

334
    int JackNetMasterInterface::Recv ( size_t size, int flags )
335
    {
336
337
        int rx_bytes;
        if ( ( ( rx_bytes = fSocket.Recv ( fRxBuffer, size, flags ) ) == SOCKET_ERROR ) && fRunning )
338
339
        {
            net_error_t error = fSocket.GetError();
340
341
342
343
            //no data isn't really a network error, so just return 0 avalaible read bytes
            if ( error == NET_NO_DATA )
                return 0;
            else if ( error == NET_CONN_ERROR )
344
345
346
            {
                //fatal connection issue, exit
                jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) );
347
                //ask to the manager to properly remove the master
348
                Exit();
349
350
351
                
                // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine.
                ThreadExit();
352
            }
moret's avatar
moret committed
353
            else
354
                jack_error ( "Error in master receive : %s", StrError ( NET_ERROR_CODE ) );
355
        }
356
357
358
359
        
        packet_header_t* header = reinterpret_cast<packet_header_t*>(fRxBuffer);
        PacketHeaderNToH(header, header);
        return rx_bytes;
360
    }
361
362
    
    int JackNetMasterInterface::Send ( size_t size, int flags )
363
    {
364
365
366
367
368
        int tx_bytes;
        packet_header_t* header = reinterpret_cast<packet_header_t*>(fTxBuffer);
        PacketHeaderHToN(header, header);
        
        if ( ( ( tx_bytes = fSocket.Send ( fTxBuffer, size, flags ) ) == SOCKET_ERROR ) && fRunning )
369
370
        {
            net_error_t error = fSocket.GetError();
371
            if ( error == NET_CONN_ERROR )
372
            {
373
374
375
                //fatal connection issue, exit
                jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) );
                Exit();
376
377
378
                
                // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine.
                ThreadExit();
379
            }
moret's avatar
moret committed
380
            else
381
                jack_error ( "Error in master send : %s", StrError ( NET_ERROR_CODE ) );
382
        }
383
        return tx_bytes;
384
    }
385
386
387
    
    bool JackNetMasterInterface::IsSynched()
    {
sletz's avatar
sletz committed
388
        if (fParams.fNetworkMode == 's') {
389
            return (fCycleOffset < 3);
sletz's avatar
sletz committed
390
        } else {
391
            return true;
sletz's avatar
sletz committed
392
        }
393
394
    }
    
395
    int JackNetMasterInterface::SyncSend()
396
    {
397
398
399
        fTxHeader.fCycle++;
        fTxHeader.fSubCycle = 0;
        fTxHeader.fDataType = 's';
400
        fTxHeader.fIsLastPckt = ( fParams.fSendMidiChannels == 0 && fParams.fSendAudioChannels == 0) ?  1 : 0;
401
402
403
404
405
406
407
408
409
        fTxHeader.fPacketSize = fParams.fMtu;
        memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
        return Send ( fTxHeader.fPacketSize, 0 );
    }

    int JackNetMasterInterface::DataSend()
    {
        uint subproc;
        //midi
410
        if ( fParams.fSendMidiChannels > 0)
411
        {
412
413
414
            //set global header fields and get the number of midi packets
            fTxHeader.fDataType = 'm';
            fTxHeader.fMidiDataSize = fNetMidiCaptureBuffer->RenderFromJackPorts();
moret's avatar
moret committed
415
            fTxHeader.fNMidiPckt = GetNMidiPckt();
416
            for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ )
417
            {
418
                fTxHeader.fSubCycle = subproc;
419
                fTxHeader.fIsLastPckt = ( ( subproc == ( fTxHeader.fNMidiPckt - 1 ) ) && (fParams.fSendAudioChannels == 0)) ? 1 : 0;
420
                fTxHeader.fPacketSize = sizeof ( packet_header_t ) + fNetMidiCaptureBuffer->RenderToNetwork ( subproc, fTxHeader.fMidiDataSize );
421
422
423
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
                    return SOCKET_ERROR;
424
425
            }
        }
426
427

        //audio
428
        if ( fParams.fSendAudioChannels > 0)
429
430
        {
            fTxHeader.fDataType = 'a';
431
432
            fTxHeader.fMidiDataSize = 0;
            fTxHeader.fNMidiPckt = 0;
433
434
435
            for ( subproc = 0; subproc < fNSubProcess; subproc++ )
            {
                fTxHeader.fSubCycle = subproc;
moret's avatar
moret committed
436
                fTxHeader.fIsLastPckt = ( subproc == ( fNSubProcess - 1 ) ) ? 1 : 0;
437
438
439
440
441
442
443
444
445
                fTxHeader.fPacketSize = fAudioTxLen;
                memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
                fNetAudioCaptureBuffer->RenderFromJackPorts ( subproc );
                if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
                    return SOCKET_ERROR;
            }
        }

        return 0;
446
447
    }

448
    int JackNetMasterInterface::SyncRecv()
449
450
    {
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
451
452
        int rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
        
453
454
455
        if ( ( rx_bytes == 0 ) || ( rx_bytes == SOCKET_ERROR ) )
            return rx_bytes;

456
        fCycleOffset = fTxHeader.fCycle - rx_head->fCycle;
457
      
458
        switch ( fParams.fNetworkMode )
459
        {
460
            case 's' :
moret's avatar
moret committed
461
462
463
464
465
                //slow mode : allow to use full bandwidth and heavy process on the slave
                //  - extra latency is set to two cycles, one cycle for send/receive operations + one cycle for heavy process on the slave
                //  - if the network is two fast, just wait the next cycle, this mode allows a shorter cycle duration for the master
                //  - this mode will skip the two first cycles, thus it lets time for data to be processed and queued on the socket rx buffer
                //the slow mode is the safest mode because it wait twice the bandwidth relative time (send/return + process)
466
                if (fCycleOffset < 2)
467
                     return 0;
468
469
                else
                    rx_bytes = Recv ( rx_head->fPacketSize, 0 );
470
471
472
473
                    
                if (fCycleOffset > 2) {
                    jack_info("Warning : '%s' runs in slow network mode, but data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
                }
474
                break;
475

476
477
478
479
480
            case 'n' :
                //normal use of the network :
                //  - extra latency is set to one cycle, what is the time needed to receive streams using full network bandwidth
                //  - if the network is too fast, just wait the next cycle, the benefit here is the master's cycle is shorter
                //  - indeed, data is supposed to be on the network rx buffer, so we don't have to wait for it
481
                if (fCycleOffset < 1)
482
483
484
                    return 0;
                else
                    rx_bytes = Recv ( rx_head->fPacketSize, 0 );
485
486
487
                    
                if (fCycleOffset != 1) 
                    jack_info("'%s' can't run in normal network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
488
                break;
489

490
491
492
493
494
495
            case 'f' :
                //fast mode suppose the network bandwith is larger than required for the transmission (only a few channels for example)
                //    - packets can be quickly received, quickly is here relative to the cycle duration
                //    - here, receive data, we can't keep it queued on the rx buffer,
                //    - but if there is a cycle offset, tell the user, that means we're not in fast mode anymore, network is too slow
                rx_bytes = Recv ( rx_head->fPacketSize, 0 );
496
497
498
                
                if (fCycleOffset != 0)
                    jack_info("'%s' can't run in fast network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
499
                break;
500
        }
501

moret's avatar
moret committed
502
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
503
504
        return rx_bytes;
    }
505
    
506
    int JackNetMasterInterface::DataRecv()
507
508
    {
        int rx_bytes = 0;
509
        uint jumpcnt = 0;
510
        uint recvd_midi_pckt = 0;
511
        uint recvd_audio_pckt = 0;
512
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
513
        
moret's avatar
moret committed
514
        while ( !fRxHeader.fIsLastPckt )
515
        {
moret's avatar
moret committed
516
517
            //how much data is queued on the rx buffer ?
            rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
518
              
moret's avatar
moret committed
519
520
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
moret's avatar
moret committed
521
            //if no data
moret's avatar
moret committed
522
            if ( ( rx_bytes == 0 ) && ( ++jumpcnt == fNSubProcess ) )
523
            {
moret's avatar
moret committed
524
525
526
527
528
529
530
531
                jack_error ( "No data from %s...", fParams.fName );
                jumpcnt = 0;
            }
            //else if data is valid,
            if ( rx_bytes && ( rx_head->fDataStream == 'r' ) && ( rx_head->fID == fParams.fID ) )
            {
                //read data
                switch ( rx_head->fDataType )
532
                {
moret's avatar
moret committed
533
                    case 'm':   //midi
534
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
moret's avatar
moret committed
535
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
536
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
537
                        fNetMidiPlaybackBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
538
                        if ( ++recvd_midi_pckt == rx_head->fNMidiPckt )
moret's avatar
moret committed
539
540
541
                            fNetMidiPlaybackBuffer->RenderToJackPorts();
                        jumpcnt = 0;
                        break;
542

moret's avatar
moret committed
543
                    case 'a':   //audio
544
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
545
546
547
                        // SL: 25/01/09
                        // if ( !IsNextPacket() )
                        //    jack_error ( "Packet(s) missing from '%s'...", fParams.fName );
548
549
550
                        if (recvd_audio_pckt++ != rx_head->fSubCycle) {
                            jack_error("Packet(s) missing from '%s'...", fParams.fSlaveNetName);
                        }
moret's avatar
moret committed
551
552
                        fRxHeader.fCycle = rx_head->fCycle;
                        fRxHeader.fSubCycle = rx_head->fSubCycle;
moret's avatar
moret committed
553
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
554
555
556
                        fNetAudioPlaybackBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        jumpcnt = 0;
                        break;
557

moret's avatar
moret committed
558
                    case 's':   //sync
559
                        /* SL: 25/01/09
moret's avatar
moret committed
560
561
                        if ( rx_head->fCycle == fTxHeader.fCycle )
                            return 0;
562
                        */
563
                        jack_info("NetMaster : overloaded, skipping receive from '%s'", fParams.fName);
564
                        return 0;
565
566
567
                }
            }
        }
568
        return rx_bytes;
569
    }
570
    
571
    void JackNetMasterInterface::EncodeSyncPacket()
572
573
574
575
576
577
    {
        //this method contains every step of sync packet informations coding
        //first of all, reset sync packet
        memset ( fTxData, 0, fPayloadSize );

        //then, first step : transport
578
579
        if (fParams.fTransportSync) {
            EncodeTransportData();
580
            TransportDataHToN( &fSendTransportData,  &fSendTransportData);
581
582
583
584
585
586
587
            //copy to TxBuffer
            memcpy ( fTxData, &fSendTransportData, sizeof ( net_transport_data_t ) );
        }
        //then others (freewheel etc.)
        //...
    }

588
    void JackNetMasterInterface::DecodeSyncPacket()
589
590
591
    {
        //this method contains every step of sync packet informations decoding process
        //first : transport
592
        if (fParams.fTransportSync) {
593
594
            //copy received transport data to transport data structure
            memcpy ( &fReturnTransportData, fRxData, sizeof ( net_transport_data_t ) );
595
            TransportDataNToH( &fReturnTransportData,  &fReturnTransportData);
596
            DecodeTransportData();
597
598
599
600
        }
        //then others
        //...
    }
601

602
603
// JackNetSlaveInterface ************************************************************************************************

moret's avatar
moret committed
604
605
    uint JackNetSlaveInterface::fSlaveCounter = 0;

606
    bool JackNetSlaveInterface::Init()
607
    {
608
        jack_log ( "JackNetSlaveInterface::Init()" );
609

610
611
        //set the parameters to send
        strcpy ( fParams.fPacketType, "params" );
612
        fParams.fProtocolVersion = SLAVE_PROTOCOL;
613
        SetPacketType ( &fParams, SLAVE_AVAILABLE );
614

615
616
617
        //init loop : get a master and start, do it until connection is ok
        net_status_t status;
        do
618
        {
619
620
            //first, get a master, do it until a valid connection is running
            do
621
            {
622
623
624
                status = GetNetMaster();
                if ( status == NET_SOCKET_ERROR )
                    return false;
625
            }
626
            while ( status != NET_CONNECTED );
627

628
629
            //then tell the master we are ready
            jack_info ( "Initializing connection with %s...", fParams.fMasterNetName );
moret's avatar
moret committed
630
            status = SendStartToMaster();
631
632
            if ( status == NET_ERROR )
                return false;
633
        }
634
        while ( status != NET_ROLLING );
635

636
637
        return true;
    }
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
    
    // Separate the connection protocol into two separated step
    
    bool JackNetSlaveInterface::InitConnection()
    {
        jack_log ( "JackNetSlaveInterface::InitConnection()" );

        //set the parameters to send
        strcpy (fParams.fPacketType, "params");
        fParams.fProtocolVersion = SLAVE_PROTOCOL;
        SetPacketType (&fParams, SLAVE_AVAILABLE);

        net_status_t status;
        do
        {
            //get a master
            status = GetNetMaster();
            if (status == NET_SOCKET_ERROR)
                return false;
        }
        while (status != NET_CONNECTED);
  
        return true;
    }
    
    bool JackNetSlaveInterface::InitRendering()
    {
        jack_log("JackNetSlaveInterface::InitRendering()");

        net_status_t status;
        do
        {
            //then tell the master we are ready
            jack_info("Initializing connection with %s...", fParams.fMasterNetName);
            status = SendStartToMaster();
            if (status == NET_ERROR)
                return false;
        }
        while (status != NET_ROLLING);   
        
        return true;
    }
680

681
    net_status_t JackNetSlaveInterface::GetNetMaster()
682
    {
683
684
        jack_log ( "JackNetSlaveInterface::GetNetMaster()" );
        //utility
685
        session_params_t host_params;
686
687
688
689
690
        int rx_bytes = 0;

        //socket
        if ( fSocket.NewSocket() == SOCKET_ERROR )
        {
691
692
            jack_error ( "Fatal error : network unreachable - %s", StrError ( NET_ERROR_CODE ) );
            return NET_SOCKET_ERROR;
693
694
        }

695
696
697
698
699
        //bind the socket
        if ( fSocket.Bind() == SOCKET_ERROR )
            jack_error ( "Can't bind the socket : %s", StrError ( NET_ERROR_CODE ) );

        //timeout on receive
700
        if ( fSocket.SetTimeOut ( SLAVE_INIT_TIMEOUT ) == SOCKET_ERROR )
701
702
            jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );

703
        //disable local loop
moret's avatar
moret committed
704
        if ( fSocket.SetLocalLoop() == SOCKET_ERROR )
705
            jack_error ( "Can't disable multicast loop : %s", StrError ( NET_ERROR_CODE ) );
706

707
708
        //send 'AVAILABLE' until 'SLAVE_SETUP' received
        jack_info ( "Waiting for a master..." );
709
710
        do
        {
711
            //send 'available'
712
713
714
            session_params_t net_params;
            SessionParamsHToN(&fParams, &net_params);
            if ( fSocket.SendTo ( &net_params, sizeof ( session_params_t ), 0, fMulticastIP ) == SOCKET_ERROR )
715
                jack_error ( "Error in data send : %s", StrError ( NET_ERROR_CODE ) );
716
                
717
            //filter incoming packets : don't exit while no error is detected
718
719
720
            memset(&net_params, 0, sizeof ( session_params_t ));
            rx_bytes = fSocket.CatchHost ( &net_params, sizeof ( session_params_t ), 0 );
            SessionParamsNToH(&net_params, &host_params);
721
            if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
722
            {
723
724
                jack_error ( "Can't receive : %s", StrError ( NET_ERROR_CODE ) );
                return NET_RECV_ERROR;
725
726
            }
        }
727
        while ( strcmp ( host_params.fPacketType, fParams.fPacketType )  && ( GetPacketType ( &host_params ) != SLAVE_SETUP ) );
728

moret's avatar
moret committed
729
        //everything is OK, copy parameters
730
        fParams = host_params;
moret's avatar
moret committed
731
732
733
734
735

        //set the new buffer sizes
        if ( SetNetBufferSize() == SOCKET_ERROR )
            jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) );

736
737
        //connect the socket
        if ( fSocket.Connect() == SOCKET_ERROR )
738
        {
739
740
            jack_error ( "Error in connect : %s", StrError ( NET_ERROR_CODE ) );
            return NET_CONNECT_ERROR;
741
742
        }

moret's avatar
moret committed
743
        return NET_CONNECTED;
744
745
    }

moret's avatar
moret committed
746
    net_status_t JackNetSlaveInterface::SendStartToMaster()
747
    {
moret's avatar
moret committed
748
        jack_log ( "JackNetSlaveInterface::SendStartToMaster" );
moret's avatar
moret committed
749

750
        //tell the master to start
751
        session_params_t net_params;
752
        SetPacketType ( &fParams, START_MASTER );
753
754
        SessionParamsHToN(&fParams, &net_params);
        if ( fSocket.Send ( &net_params, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR )
755
        {
756
757
            jack_error ( "Error in send : %s", StrError ( NET_ERROR_CODE ) );
            return ( fSocket.GetError() == NET_CONN_ERROR ) ? NET_ERROR : NET_SEND_ERROR;
758
        }
759
        return NET_ROLLING;
760
761
    }

762
    void JackNetSlaveInterface::SetParams()
moret's avatar
moret committed
763
    {
764
        jack_log ( "JackNetSlaveInterface::SetParams" );
moret's avatar
moret committed
765
766
767

        JackNetInterface::SetParams();

768
769
        fTxHeader.fDataStream = 'r';
        fRxHeader.fDataStream = 's';
moret's avatar
moret committed
770
771

        //midi net buffers
772
773
        fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fRxData );
        fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fTxData );
moret's avatar
moret committed
774
775

        //audio net buffers
776
777
        fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
        fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
moret's avatar
moret committed
778
779
780
781
782
783

        //audio netbuffer length
        fAudioTxLen = sizeof ( packet_header_t ) + fNetAudioPlaybackBuffer->GetSize();
        fAudioRxLen = sizeof ( packet_header_t ) + fNetAudioCaptureBuffer->GetSize();
    }

784
    int JackNetSlaveInterface::Recv ( size_t size, int flags )
785
    {
786
787
788
789
790
791
792
793
794
795
796
797
        int rx_bytes = fSocket.Recv ( fRxBuffer, size, flags );
        //handle errors
        if ( rx_bytes == SOCKET_ERROR )
        {
            net_error_t error = fSocket.GetError();
            //no data isn't really an error in realtime processing, so just return 0
            if ( error == NET_NO_DATA )
                jack_error ( "No data, is the master still running ?" );
            //if a network error occurs, this exception will restart the driver
            else if ( error == NET_CONN_ERROR )
            {
                jack_error ( "Connection lost." );
moret's avatar
moret committed
798
                throw JackNetException();
799
800
            }
            else
sletz's avatar
sletz committed
801
                jack_error ( "Fatal error in slave receive : %s", StrError ( NET_ERROR_CODE ) );
802
        }
803
804
805
        
        packet_header_t* header = reinterpret_cast<packet_header_t*>(fRxBuffer);
        PacketHeaderNToH(header, header);
806
        return rx_bytes;
807
808
    }

809
    int JackNetSlaveInterface::Send ( size_t size, int flags )
810
    {
811
812
        packet_header_t* header = reinterpret_cast<packet_header_t*>(fTxBuffer);
        PacketHeaderHToN(header, header);
813
        int tx_bytes = fSocket.Send ( fTxBuffer, size, flags );
814
         
815
816
        //handle errors
        if ( tx_bytes == SOCKET_ERROR )
817
818
        {
            net_error_t error = fSocket.GetError();
819
820
            //if a network error occurs, this exception will restart the driver
            if ( error == NET_CONN_ERROR )
821
            {
822
                jack_error ( "Connection lost." );
moret's avatar
moret committed
823
                throw JackNetException();
824
            }
825
            else
sletz's avatar
sletz committed
826
                jack_error ( "Fatal error in slave send : %s", StrError ( NET_ERROR_CODE ) );
827
828
829
830
        }
        return tx_bytes;
    }

831
    int JackNetSlaveInterface::SyncRecv()
832
    {
833
834
835
836
        int rx_bytes = 0;
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
        //receive sync (launch the cycle)
        do
837
        {
838
839
840
841
842
            rx_bytes = Recv ( fParams.fMtu, 0 );
            //connection issue, send will detect it, so don't skip the cycle (return 0)
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
        }
843
844
        while ((strcmp(rx_head->fPacketType, "header") != 0) && (rx_head->fDataType != 's'));
        
moret's avatar
moret committed
845
        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
846
847
848
849
850
851
        return rx_bytes;
    }

    int JackNetSlaveInterface::DataRecv()
    {
        uint recvd_midi_pckt = 0;
852
        uint recvd_audio_pckt = 0;
853
854
855
        int rx_bytes = 0;
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );

moret's avatar
moret committed
856
        while ( !fRxHeader.fIsLastPckt )
857
        {
moret's avatar
moret committed
858
859
            rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
            //error here, problem with recv, just skip the cycle (return -1)
moret's avatar
moret committed
860

moret's avatar
moret committed
861
862
863
            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
            if ( rx_bytes && ( rx_head->fDataStream == 's' ) && ( rx_head->fID == fParams.fID ) )
864
            {
moret's avatar
moret committed
865
                switch ( rx_head->fDataType )
866
                {
moret's avatar
moret committed
867
868
869
                    case 'm':   //midi
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                        fRxHeader.fCycle = rx_head->fCycle;
moret's avatar
moret committed
870
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
871
872
873
874
                        fNetMidiCaptureBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
                        if ( ++recvd_midi_pckt == rx_head->fNMidiPckt )
                            fNetMidiCaptureBuffer->RenderToJackPorts();
                        break;
875

moret's avatar
moret committed
876
877
                    case 'a':   //audio
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
878
879
880
                        //SL: 25/01/09
                        // if ( !IsNextPacket() )
                        //    jack_error ( "Packet(s) missing..." );
881
882
883
                        if (recvd_audio_pckt++ != rx_head->fSubCycle) {
                            jack_error("Packet(s) missing from '%s'...", fParams.fMasterNetName);
                        }
moret's avatar
moret committed
884
885
                        fRxHeader.fCycle = rx_head->fCycle;
                        fRxHeader.fSubCycle = rx_head->fSubCycle;
moret's avatar
moret committed
886
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
moret's avatar
moret committed
887
888
                        fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        break;
889

moret's avatar
moret committed
890
891
892
                    case 's':   //sync
                        jack_info ( "NetSlave : overloaded, skipping receive." );
                        return 0;
893
                }
894
895
            }
        }
896
897
        fRxHeader.fCycle = rx_head->fCycle;
        return 0;
898
899
    }

900
    int JackNetSlaveInterface::SyncSend()
901
    {
902
903
904
905
906
        //tx header
        if ( fParams.fSlaveSyncMode )
            fTxHeader.fCycle = fRxHeader.fCycle;
        else
            fTxHeader.fCycle++;
907
908
        fTxHeader.fSubCycle = 0;
        fTxHeader.fDataType = 's';
909
        fTxHeader.fIsLastPckt = ( fParams.fReturnMidiChannels == 0 && fParams.fReturnAudioChannels == 0) ?  1 : 0;
910
911
912
913
914
        fTxHeader.fPacketSize = fParams.fMtu;
        memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
        return Send ( fTxHeader.fPacketSize, 0 );
    }