`Page 1/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`
`Copyright (c) 2001 BeComm Corporation
`
`Filename:
`
` clocksync.c
`
`Group Name:
`
` todo
`
`Group Overview:
`
` Used in conjunction with timesync.
`
` Used to propogate a master/render clock pair over
` a network link.
`
` Passes the following elements:
`- epoch from the master clock.
`- frequency/divisor from the render clock. (NO LONGER REQUIRED, REMOVED)
`
` This is enough to manage timed delivery of video.
`
` NOTE: Transports only in forward direction (currently) - updates to the
` render clock are not propogated backwards.
`
`Owner:
`
` Guy Carpenter (guyc) 16-Aug-2001
`
`-----------------------------------------------------------------------------*/
`#define SOS_DEBUG_ZONE "/beads/clocksync"
`#include <sosstrings.h>
`#include <sosmultimedia.h>
`#include "timesync.h"
`
`SOS_SOURCE_VERSION("$Id: clocksync.c,v 1.12 2001/11/09 02:46:36 guyc Exp $");
`
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`Named Constants
`-----------------------------------------------------------------------------*/
`
`/*
`
`1 2
`
`3 4
`
`5 6
`
`7 8
`
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`
`Page 1 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/be…/…/main/clocksync.c
`Page 2/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
` * Name of bead
` */
`static
`const char BEAD_NAME[] = "clocksync";
`const char LOOPBACK_CONTENTTYPE[] = "clocksync/loopback";
`
`#define TIMER_INTERVAL 4000
`#define TIMER_INITIAL_DELAY 200
`
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`Masks
`-----------------------------------------------------------------------------*/
`
`/*
` * Order here is important: we use the bit
` * positions to efficiently compute the length.
` */
`#define FLAG_MASTERSHIFT 16
`#define FLAG_RENDERSHIFT 18
`#define MASK_SIZE 3
`#define MASK_LENGTH 0xFFFF
`#define FLAG_MASTEREPOCH 1<<(FLAG_MASTERSHIFT)
`#define FLAG_MASTERFREQ 1<<(FLAG_MASTERSHIFT+1)
`#define FLAG_RENDEREPOCH 1<<(FLAG_RENDERSHIFT)
`#define FLAG_RENDERFREQ 1<<(FLAG_RENDERSHIFT+1)
`#define FLAG_LOOPBACKREQ 1<<20
`#define FLAG_DONTFORWARD 1<<21
`#define FLAG_UNCONDITIONAL_MASK (FLAG_LOOPBACKREQ | FLAG_DONTFORWARD)
`#define CONSTANT_LENGTH 2 /* hostid and length+flags in 2x32 bits */
`#define MAX_VARIABLE_LENGTH 6 /* up to 6 other 32-bit values */
`
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`Structs
`-----------------------------------------------------------------------------*/
`
`typedef struct STREAM_CONTEXT {
` SOS_UINT32 HostId;
` SOS_CLOCK_TICK StartTime;
` SOS_ISAMPLECLOCK * IMasterClock;
` SOS_ISAMPLECLOCK * IRenderClock;
` SOS_TIMER_ID TimerId;
` SOS_BOOLEAN RenderUpdate;
` SOS_PATH * ReturnPath;
`} STREAM_CONTEXT;
`
`46
`47
`48
`49
`50
`51
`52
`53
`54
`55
`56
`57
`58
`59
`60
`61
`62
`63
`64
`65
`66
`67
`68
`69
`70
`71
`72
`73
`74
`75
`76
`77
`78
`79
`80
`81
`82
`83
`84
`85
`86
`87
`88
`89
`90
`
`Page 2 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/be…/…/main/clocksync.c
`Page 3/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
`91
`92
`93
`94
`95
`96
`97
`98
`99
`100
`101
`102
`103
`104
`105
`106
`107
`108
`109
`110
`111
`112
`113
`114
`115
`116
`117
`118
`119
`120
`121
`122
`123
`124
`125
`126
`127
`128
`129
`130
`131
`132
`133
`134
`135
`
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`Context create and destory
`-----------------------------------------------------------------------------*/
`
`/*++
`Routine Name:
`
` ClockSync_ContextCreate
`
`Routine Description:
`
` Attempt to allocate a ClockSync session and all the resources it requires.
`
`Parameters:
`
` None.
`
`Return Value:
`
` UPDATE_CONTEXT * -
` A valid pointer to a session context on success.
`
` A NULL pointer if an error occured.
`
`--*/
`static
`STREAM_CONTEXT *
`ClockSync_ContextCreate(
` void
`)
`{
` STREAM_CONTEXT *context;
`
` SOS_DEBUGOUT_FUNC_TRACE("ClockSync_ContextCreate called\n");
`
` context = SOS_Mem_Alloc(sizeof(*context));
` if (context) {
` SOS_memset(context, 0, sizeof(*context));
` TimeSync_HostIdGet(&context->HostId);
` context->StartTime = SOS_Clock_TickGet();
`// context->RenderUpdate = SOS_True; // REVISIT - set via configuration
`
` }
`
` return context;
`
`Page 3 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/be…/…/main/clocksync.c
`Page 4/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
`136
`137
`138
`139
`140
`141
`142
`143
`144
`145
`146
`147
`148
`149
`150
`151
`152
`153
`154
`155
`156
`157
`158
`159
`160
`161
`162
`163
`164
`165
`166
`167
`168
`169
`170
`171
`172
`173
`174
`175
`176
`177
`178
`179
`180
`
`}
`
`void
`ClockSync_ContextDestroy(
` STREAM_CONTEXT * Context
`)
`{
` if (Context) {
` SOS_Interface_Release(Context->IMasterClock);
` SOS_Interface_Release(Context->IRenderClock);
`
` SOS_Mem_Free(Context);
` }
`}
`
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`Edge Handlers
`-----------------------------------------------------------------------------*/
`
`/*++
`Routine Name:
`
` ClockSync_KeyCreate
`
`Routine Description:
`
` Creates a new key for each session.
`
`Parameters:
`
` SOS_PATH *Path - [in]
` The new Path to create a Key for
`
` SOS_MESSAGE *Message - [in]
`
`Return Value:
`
` SOS_STATUS -
` SOS_PathBuild_Stop on success.
`
` SOS_Error if something goes wrong.
`--*/
`static
`SOS_STATUS
`ClockSync_KeyCreate(
`
`Page 4 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/be…/…/main/clocksync.c
`Page 5/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
`181
`182
`183
`184
`185
`186
`187
`188
`189
`190
`191
`192
`193
`194
`195
`196
`197
`198
`199
`200
`201
`202
`203
`204
`205
`206
`207
`208
`209
`210
`211
`212
`213
`214
`215
`216
`217
`218
`219
`220
`221
`222
`223
`224
`225
`
` SOS_PATH *Path,
` SOS_MESSAGE *Message
`)
`{
` static SOS_UINT32 s_UniqueId = 0;
` SOS_REGOBJECT* uniqueSessionKey;
`
` uniqueSessionKey = SOS_UInt32_Create(s_UniqueId++);
` SOS_Path_SessionKeySet(Path, uniqueSessionKey);
` SOS_RegObject_Release(uniqueSessionKey);
`
` return SOS_PathBuild_Stop;
`}
`
`static
`SOS_ISAMPLECLOCK *
`FindClock(
` SOS_PATH * Path,
` const char * Name
`)
`{
` SOS_REGOBJECT *clock;
` SOS_ISAMPLECLOCK *iSampleClock = NULL;
`
` if (SOS_SUCCEEDED(
` SOS_Path_AttributeGet(
` Path,
` Name,
` &clock))) {
` SOS_RegObject_InterfaceGet(
` clock,
` SOS_ISAMPLECLOCK_ID,
` (void**)&iSampleClock
` );
` SOS_RegObject_Release(clock);
` }
` return iSampleClock;
`}
`
`static
`SOS_UINT32
`ClockSync_LengthCompute(
` SOS_UINT32 Flags
`)
`
`Page 5 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/be…/…/main/clocksync.c
`Page 6/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
`226
`227
`228
`229
`230
`231
`232
`233
`234
`235
`236
`237
`238
`239
`240
`241
`242
`243
`244
`245
`246
`247
`248
`249
`250
`251
`252
`253
`254
`255
`256
`257
`258
`259
`260
`261
`262
`263
`264
`265
`266
`267
`268
`269
`270
`
`{
` /*
` * We always send a hostid and length+flags
` */
` SOS_UINT32 length = 2;
` /*
` * Flags are structured such that the 64-bit
` * entries are in bit positions 0x0010 and 1000
` * and the 32-bit entries are in positions 0001 and 0100.
` * This means that we can compute the length by adding
` * 0011 + 1100>>2.
` */
` length += (Flags>>FLAG_MASTERSHIFT & MASK_SIZE) +
` (Flags>>FLAG_RENDERSHIFT & MASK_SIZE);
` return length;
`}
`
`static
`SOS_STATUS
`ClockSync_Encode(
` STREAM_CONTEXT * Context,
` SOS_MESSAGE * Message,
` SOS_UINT32 Flags
`)
`{
` SOS_STATUS status;
` SOS_UINT32 length = ClockSync_LengthCompute(Flags);
` SOS_UINT32 *header = SOS_Mem_Alloc(sizeof(SOS_UINT32)*length);
` SOS_UINT32 *ptr = header;
` SOS_UINT32 actualFlags = Flags & FLAG_UNCONDITIONAL_MASK;
` SOS_UINT32 actualLength = 0;
`
` if (header) {
` ptr++; /* later set to (SOS_HTOLEL((length-2) | Flags) */
` *ptr++ = SOS_HTOLEL(Context->HostId);
`
` if (Flags & FLAG_MASTERFREQ) {
` SOS_UINT32 frequency, divisor;
`
` SOS_DEBUGOUT_DETAIL("Encoding master frequency\n");
`
` status = Context->IMasterClock->FrequencyGet(
` Context->IMasterClock,
` &frequency,
`
`Page 6 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/be…/…/main/clocksync.c
`Page 7/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
` &divisor
` );
` if (SOS_SUCCEEDED(status)) {
` *ptr++ = SOS_HTOLEL(frequency);
` *ptr++ = SOS_HTOLEL(divisor);
` actualFlags |= FLAG_MASTERFREQ;
` }
` }
`
` if (Flags & FLAG_MASTEREPOCH) {
` SOS_UINT32 epoch;
`
` SOS_DEBUGOUT_DETAIL("Encoding master epoch\n");
`
` status = Context->IMasterClock->EpochGet(
` Context->IMasterClock,
` &epoch
` );
` if (SOS_SUCCEEDED(status)) {
` *ptr++ = SOS_HTOLEL(epoch);
` actualFlags |= FLAG_MASTEREPOCH;
` }
`
` }
`
` if (Flags & FLAG_RENDERFREQ) {
` SOS_UINT32 frequency, divisor;
`
` SOS_DEBUGOUT_DETAIL("Encoding render frequency\n");
`
` status = Context->IRenderClock->FrequencyGet(
` Context->IRenderClock,
` &frequency,
` &divisor
` );
` if (SOS_SUCCEEDED(status)) {
` *ptr++ = SOS_HTOLEL(frequency);
` *ptr++ = SOS_HTOLEL(divisor);
` actualFlags |= FLAG_RENDERFREQ;
` }
` }
`
` if (Flags & FLAG_RENDEREPOCH) {
` SOS_UINT32 epoch;
`
`271
`272
`273
`274
`275
`276
`277
`278
`279
`280
`281
`282
`283
`284
`285
`286
`287
`288
`289
`290
`291
`292
`293
`294
`295
`296
`297
`298
`299
`300
`301
`302
`303
`304
`305
`306
`307
`308
`309
`310
`311
`312
`313
`314
`315
`
`Page 7 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/be…/…/main/clocksync.c
`Page 8/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
` SOS_DEBUGOUT_DETAIL("Encoding render epoch\n");
`
` status = Context->IRenderClock->EpochGet(
` Context->IRenderClock,
` &epoch
` );
` if (SOS_SUCCEEDED(status)) {
` *ptr++ = SOS_HTOLEL(epoch);
` actualFlags |= FLAG_RENDEREPOCH;
` }
` }
`
` actualLength = ptr-header;
`
` SOS_ASSERT(
` (SOS_UINT32)actualLength<=length,
` "Error in header length computation"
` );
`
` header[0] = (SOS_HTOLEL(actualLength-2)) | actualFlags;
`
` status = SOS_Message_HeadDataPush(
` Message,
` header,
` actualLength * sizeof(SOS_UINT32),
` SOS_Mem_Free
` );
` } else {
` status = SOS_ErrorResourceAllocation;
` }
`
` return status;
`}
`
`static
`void
`ClockSync_LoopBack(
` void * Context
`)
`{
` SOS_MESSAGE *message;
` STREAM_CONTEXT *context = Context;
` SOS_DEBUGOUT_FUNC_TRACE("ClockSync_LoopBack\n");
`
`316
`317
`318
`319
`320
`321
`322
`323
`324
`325
`326
`327
`328
`329
`330
`331
`332
`333
`334
`335
`336
`337
`338
`339
`340
`341
`342
`343
`344
`345
`346
`347
`348
`349
`350
`351
`352
`353
`354
`355
`356
`357
`358
`359
`360
`
`Page 8 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/be…/…/main/clocksync.c
`Page 9/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
`361
`362
`363
`364
`365
`366
`367
`368
`369
`370
`371
`372
`373
`374
`375
`376
`377
`378
`379
`380
`381
`382
`383
`384
`385
`386
`387
`388
`389
`390
`391
`392
`393
`394
`395
`396
`397
`398
`399
`400
`401
`402
`403
`404
`405
`
` message = SOS_Message_Create();
`
` ClockSync_Encode(
` context,
` message,
` FLAG_RENDEREPOCH | FLAG_DONTFORWARD
` );
`
` SOS_DEBUGOUT_DETAIL("Sending loopback path data\n");
` SOS_Path_MessageSend(context->ReturnPath, message);
`}
`
`static
`SOS_STATUS
`ClockSync_Decode(
` STREAM_CONTEXT * Context,
` SOS_MESSAGE * Message,
` SOS_PATH * Path
`)
`{
` SOS_STATUS status = SOS_Success;
` SOS_UINT32 header1[CONSTANT_LENGTH];
` SOS_UINT32 header2[MAX_VARIABLE_LENGTH];
` SOS_UINT32 *ptr = header2;
` size_t bytesRemoved;
` SOS_UINT32 length;
` SOS_UINT32 flags;
` SOS_UINT32 hostId;
` SOS_UINT32 offset;
` SOS_BOOLEAN haveOffset = SOS_False;
`
` /* extract constant part of header */
`
` status = SOS_Message_HeadDataPop(
` Message,
` CONSTANT_LENGTH * sizeof(SOS_UINT32),
` header1,
` &bytesRemoved);
`
` SOS_ASSERT_SOFT_ERROR(
` bytesRemoved==CONSTANT_LENGTH*sizeof(SOS_UINT32),
` "Message does not contain enough data"
` );
`
` flags = SOS_LETOHL(header1[0]);
`
`Page 9 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/clocksync.c
`Page 10/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
`406
`407
`408
`409
`410
`411
`412
`413
`414
`415
`416
`417
`418
`419
`420
`421
`422
`423
`424
`425
`426
`427
`428
`429
`430
`431
`432
`433
`434
`435
`436
`437
`438
`439
`440
`441
`442
`443
`444
`445
`446
`447
`448
`449
`450
`
` hostId = SOS_LETOHL(header1[1]);
` length = flags & MASK_LENGTH;
`
` if (SOS_SUCCEEDED(TimeSync_OffsetGet(hostId, &offset))) {
` haveOffset = SOS_True;
` }
`
` SOS_ASSERT_SOFT_ERROR(
` length<=MAX_VARIABLE_LENGTH,
` "Length exceeded expected maximum"
` );
`
` /* recover constant part of header */
`
` SOS_Message_HeadDataPop(
` Message,
` length * sizeof(SOS_UINT32),
` header2,
` &bytesRemoved);
`
` SOS_ASSERT_SOFT_ERROR(
` bytesRemoved==length*sizeof(SOS_UINT32),
` "Message does not contain enough data"
` );
`
` /*
` * Extract those elements found in mask
` */
`
` /* master clock frequency */
`
` if (flags & FLAG_MASTERFREQ) {
` SOS_UINT32 frequency = SOS_LETOHL(*ptr++);
` SOS_UINT32 divisor = SOS_LETOHL(*ptr++);
`
` SOS_DEBUGOUT_DETAIL("ClockSync decoding master freq\n");
`
` status = Context->IMasterClock->FrequencySet(
` Context->IMasterClock,
` frequency,
` divisor
` );
`
` SOS_ASSERT_SOFT_ERROR(
` SOS_SUCCEEDED(status),
`
`Page 10 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/clocksync.c
`Page 11/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
`451
`452
`453
`454
`455
`456
`457
`458
`459
`460
`461
`462
`463
`464
`465
`466
`467
`468
`469
`470
`471
`472
`473
`474
`475
`476
`477
`478
`479
`480
`481
`482
`483
`484
`485
`486
`487
`488
`489
`490
`491
`492
`493
`494
`495
`
` "Error updating master clock frequency"
` );
` }
`
` /* master clock epoch */
`
` if (flags & FLAG_MASTEREPOCH) {
` SOS_UINT32 epoch = SOS_LETOHL(*ptr++);
`
` SOS_DEBUGOUT_DETAIL("ClockSync decoding master epoch\n");
`
` if (haveOffset) {
` SOS_DEBUGOUT_DETAIL(
` "Remote master epoch=%lu corrected by offset of %ld to local master epoch=%lu\n",
` epoch,
` offset,
` epoch - offset);
` epoch -= offset;
` } else {
` SOS_DEBUGOUT_DETAIL(
` "No offset available - using session time as epoch\n"
` );
` epoch = Context->StartTime;
` }
`
` status = Context->IMasterClock->Update(
` Context->IMasterClock,
` epoch,
` 0
` );
`
` SOS_ASSERT_SOFT_ERROR(
` SOS_SUCCEEDED(status),
` "Error updating master clock"
` );
` }
`
` /* render clock frequency */
`
` if (flags & FLAG_RENDERFREQ) {
` SOS_UINT32 frequency = SOS_LETOHL(*ptr++);
` SOS_UINT32 divisor = SOS_LETOHL(*ptr++);
`
` SOS_DEBUGOUT_DETAIL("ClockSync decoding render frequency to clock %p\n",
` Context->IRenderClock->Interface.Object);
`
`Page 11 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/clocksync.c
`Page 12/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
`496
`497
`498
`499
`500
`501
`502
`503
`504
`505
`506
`507
`508
`509
`510
`511
`512
`513
`514
`515
`516
`517
`518
`519
`520
`521
`522
`523
`524
`525
`526
`527
`528
`529
`530
`531
`532
`533
`534
`535
`536
`537
`538
`539
`540
`
` status = Context->IRenderClock->FrequencySet(
` Context->IRenderClock,
` frequency,
` divisor
` );
`
` SOS_ASSERT_SOFT_ERROR(
` SOS_SUCCEEDED(status),
` "Error updating render clock frequency"
` );
` }
`
` /* render clock epoch */
`
` if (flags & FLAG_RENDEREPOCH) {
` SOS_UINT32 epoch = SOS_LETOHL(*ptr++);
`
` SOS_DEBUGOUT_DETAIL("ClockSync decoding render epoch remote %lu local %lu to clock %p\n",
` epoch,
` haveOffset ? (epoch - offset) : 0,
` Context->IRenderClock->Interface.Object);
`
` if (haveOffset) {
` epoch -= offset;
` } else {
` epoch = Context->StartTime;
` }
`
` status = Context->IRenderClock->Update(
` Context->IRenderClock,
` epoch,
` 0
` );
`
`
` SOS_ASSERT_SOFT_ERROR(
` SOS_SUCCEEDED(status),
` "Error updating render clock"
` );
` }
`
` if (flags & FLAG_LOOPBACKREQ) {
`
` SOS_DEBUGOUT_DETAIL("ClockSync received loopback request\n");
`
`Page 12 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/clocksync.c
`Page 13/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
`541
`542
`543
`544
`545
`546
`547
`548
`549
`550
`551
`552
`553
`554
`555
`556
`557
`558
`559
`560
`561
`562
`563
`564
`565
`566
`567
`568
`569
`570
`571
`572
`573
`574
`575
`576
`577
`578
`579
`580
`581
`582
`583
`584
`585
`
` if (!Context->ReturnPath) {
` SOS_REGOBJECT *contentType =
` SOS_String_CreateFromString(LOOPBACK_CONTENTTYPE);
` Context->ReturnPath = SOS_Path_Create(Path);
` SOS_Path_AttributeSet(
` Context->ReturnPath,
` "Content-Type",
` contentType
` );
` SOS_RegObject_Release(contentType);
` }
` ClockSync_LoopBack(Context);
` }
`
` if (flags & FLAG_DONTFORWARD) {
` SOS_DEBUGOUT_DETAIL("ClockSync received dontforward request\n");
` /*
` * We return SOS_True to indicate the message should not
` * be forwarded.
` */
` status = SOS_True;
` }
`
` return status;
`}
`
`static
`SOS_STATUS
`ClockSync_EncodeHandler(
` SOS_PATH *Path,
` SOS_MESSAGE *Message
`)
`{
` SOS_STATUS status = SOS_Success;
` STREAM_CONTEXT * context;
`
` status = SOS_Path_SessionContextPeek(Path, (void**)&context);
`
` SOS_DEBUGOUT_FUNC_TRACE("ClockSync_EncodeHandler\n");
`
` status = ClockSync_Encode(
` context,
`
`Page 13 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/clocksync.c
`Page 14/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
`586
`587
`588
`589
`590
`591
`592
`593
`594
`595
`596
`597
`598
`599
`600
`601
`602
`603
`604
`605
`606
`607
`608
`609
`610
`611
`612
`613
`614
`615
`616
`617
`618
`619
`620
`621
`622
`623
`624
`625
`626
`627
`628
`629
`630
`
` Message,
` (context->IMasterClock ? FLAG_MASTEREPOCH : 0)
` );
`
`
` if (SOS_SUCCEEDED(status)) {
` status = SOS_Path_MessageSend(
` Path,
` Message
` );
` } else {
` /* some sort of error prevented message from being sent */
` SOS_Message_Destroy(Message);
` }
`
` return status;
`}
`
`static
`SOS_STATUS
`ClockSync_DecodeHandler(
` SOS_PATH *Path,
` SOS_MESSAGE *Message
`)
`{
` SOS_STATUS status = SOS_Success;
` STREAM_CONTEXT * context;
`
` status = SOS_Path_SessionContextPeek(Path, (void**)&context);
`
` SOS_DEBUGOUT_FUNC_TRACE("ClockSync_DecodeHandler\n");
`
` status = ClockSync_Decode(
` context,
` Message,
` Path
` );
`
` if (status == SOS_Success) {
` status = SOS_Path_MessageSend(Path, Message);
` } else if (status == SOS_True) {
` /* we aren't forwarding the message, but everything is good */
` SOS_Message_Destroy(Message);
` status = SOS_Success;
` } else {
`
`Page 14 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/clocksync.c
`Page 15/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
`631
`632
`633
`634
`635
`636
`637
`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
`
` SOS_Message_Destroy(Message);
` }
`
` return status;
`}
`
`static
`SOS_STATUS
`ClockSync_MasterEncodeHandler(
` SOS_PATH *Path,
` SOS_MESSAGE *Message
`)
`{
` SOS_STATUS status = SOS_Success;
` STREAM_CONTEXT * context;
`
` status = SOS_Path_SessionContextPeek(Path, (void**)&context);
`
` SOS_DEBUGOUT_FUNC_TRACE("ClockSync_MasterEncodeHandler\n");
`
` if (!context->IMasterClock) {
` context->IMasterClock = FindClock(
` Path,
` SOS_MASTERCLOCK_NAME);
` }
`
` if (!context->IRenderClock) {
` context->IRenderClock = FindClock(
` Path,
` SOS_RENDERCLOCK_NAME);
` }
`
` status = ClockSync_Encode(
` context,
` Message,
` FLAG_LOOPBACKREQ | (context->IMasterClock ? FLAG_MASTEREPOCH : 0)
` );
`
`
` if (SOS_SUCCEEDED(status)) {
` status = SOS_Path_MessageSend(
` Path,
` Message
` );
` } else {
`
`Page 15 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/clocksync.c
`Page 16/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
` /* some sort of error prevented message from being sent */
` SOS_Message_Destroy(Message);
` }
`
` return status;
`}
`
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`Timer
`+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
`
`#if 0
`
`static
`SOS_STATUS
`ClockSync_TimerStart(
` STREAM_CONTEXT * Context
`)
`{
` SOS_STATUS status;
`
` status = SOS_Timer_PeriodicSchedule(
` TIMER_INITIAL_DELAY,
` TIMER_INTERVAL,
` ClockSync_LoopBack,
` Context,
` &Context->TimerId
` );
`
` return status;
`}
`
`static
`SOS_STATUS
`ClockSync_TimerStop(
` STREAM_CONTEXT * Context
`)
`{
` SOS_STATUS status;
`
` status = SOS_Timer_Cancel(Context->TimerId);
`
` return status;
`}
`
`676
`677
`678
`679
`680
`681
`682
`683
`684
`685
`686
`687
`688
`689
`690
`691
`692
`693
`694
`695
`696
`697
`698
`699
`700
`701
`702
`703
`704
`705
`706
`707
`708
`709
`710
`711
`712
`713
`714
`715
`716
`717
`718
`719
`720
`
`Page 16 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/clocksync.c
`Page 17/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
`721
`722
`723
`724
`725
`726
`727
`728
`729
`730
`731
`732
`733
`734
`735
`736
`737
`738
`739
`740
`741
`742
`743
`744
`745
`746
`747
`748
`749
`750
`751
`752
`753
`754
`755
`756
`757
`758
`759
`760
`761
`762
`763
`764
`765
`
`#endif
`
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`Session init and uninit
`+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
`
`/*++
`Routine Name:
`
` ClockSync_SessionInit
`
`Routine Description:
`
` Called by Strings when ClockSync_KeyCreate returns that a new
` ClockSync session should be created. It allocates a session
` context and assocates it with the Path that is passed in.
`
`Parameters:
`
` SOS_PATH *Path - [in]
` The path assocated with the bead to be created.
`
`Return Value:
`
` SOS_STATUS -
` SOS_Success if a context was created and succesfully assocated
` with a path.
`
` SOS_Error otherwise.
`
`--*/
`static
`SOS_STATUS
`ClockSync_SessionInit(
` SOS_PATH *Path
`)
`{
` SOS_STATUS status = SOS_Success;
` STREAM_CONTEXT *context = ClockSync_ContextCreate();
`
` SOS_DEBUGOUT_FUNC_TRACE("ClockSync_SessionInit called\n");
`
` if (context) {
` /* assocate the new context with a path */
` status = SOS_Path_SessionContextPut(Path, context);
`
`Page 17 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/clocksync.c
`Page 18/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
`766
`767
`768
`769
`770
`771
`772
`773
`774
`775
`776
`777
`778
`779
`780
`781
`782
`783
`784
`785
`786
`787
`788
`789
`790
`791
`792
`793
`794
`795
`796
`797
`798
`799
`800
`801
`802
`803
`804
`805
`806
`807
`808
`809
`810
`
` } else {
` status = SOS_ErrorResourceAllocation;
` }
` return status;
`}
`
`/*++
`Routine Name:
`
` ClockSync_SessionUninit
`
`Routine Description:
`
` Called by Strings to free all memory assocated with this session.
`
`Parameters:
`
` SOS_PATH *Path - [in]
` The path assocated with the session to be destroyed.
`
`Return Value:
`
` SOS_STATUS -
` SOS_Success
` on successful uninit.
`
` SOS_Error
` if the context could not be retrieved.
`
`--*/
`static
`SOS_STATUS
`ClockSync_SessionUninit(
` SOS_PATH *Path
`)
`{
` SOS_STATUS status;
` STREAM_CONTEXT *context;
`
` SOS_DEBUGOUT_FUNC_TRACE("ClockSync_SessionUninit called\n");
`
` /* find the session context assocated with this path */
` status = SOS_Path_SessionContextPeek(Path, (void**)&context);
`
` /* make sure we found a valid context */
`
`Page 18 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/clocksync.c
`Page 19/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
`811
`812
`813
`814
`815
`816
`817
`818
`819
`820
`821
`822
`823
`824
`825
`826
`827
`828
`829
`830
`831
`832
`833
`834
`835
`836
`837
`838
`839
`840
`841
`842
`843
`844
`845
`846
`847
`848
`849
`850
`851
`852
`853
`854
`855
`
` if (SOS_SUCCEEDED(status) && context) {
` ClockSync_ContextDestroy(context);
` }
`
` return status;
`}
`
`static
`SOS_STATUS
`ClockSync_PathInit(
` SOS_PATH * Path
`)
`{
` SOS_STATUS status = SOS_Success;
` STREAM_CONTEXT *context;
`
` status = SOS_Path_SessionContextPeek(Path, (void**)&context);
`
` /* PathInit is called after the context is created in SessionInit */
`
` SOS_DEBUGOUT_FUNC_TRACE("ClockSync_PathInit called\n");
`
` if (context) {
`
` if (!context->IMasterClock || !context->IRenderClock) {
` context->IMasterClock = FindClock(
` Path,
` SOS_MASTERCLOCK_NAME);
`
` context->IRenderClock = FindClock(
` Path,
` SOS_RENDERCLOCK_NAME);
`
` if (!context->IMasterClock || !context->IRenderClock) {
` SOS_ASSERT_ASSUMPTION(0,"Need both master clock and render clock!");
` status = SOS_Error;
` }
` }
` }
`
` return status;
`}
`
`/*
`
`Page 19 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/clocksync.c
`Page 20/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
`856
`857
`858
`859
`860
`861
`862
`863
`864
`865
`866
`867
`868
`869
`870
`871
`872
`873
`874
`875
`876
`877
`878
`879
`880
`881
`882
`883
`884
`885
`886
`887
`888
`889
`890
`891
`892
`893
`894
`895
`896
`897
`898
`899
`900
`
` * The master edge just sets the render clock to be a reference
` * to the master clock. There is no handler code for this edge,
` * so it just calls message send.
` */
`
`static
`SOS_STATUS
`ClockSync_MasterPathInit(
` SOS_PATH * Path
`)
`{
` SOS_STATUS status = SOS_Success;
` STREAM_CONTEXT *context;
`
` status = SOS_Path_SessionContextPeek(Path, (void**)&context);
`
` /* PathInit is called after the context is created in SessionInit */
`
` SOS_DEBUGOUT_FUNC_TRACE("ClockSync_MasterPathInit called\n");
`
` if (context) {
` SOS_REGOBJECT *masterClock;
` if (SOS_SUCCEEDED(
` SOS_Path_AttributeGet(
` Path,
` SOS_MASTERCLOCK_NAME,
` &masterClock
` ))) {
` SOS_Path_AttributeSet(
` Path,
` SOS_RENDERCLOCK_NAME,
` masterClock
` );
` SOS_RegObject_Release(masterClock);
` } else {
` SOS_ASSERT_ASSUMPTION(
` masterClock,
` "Required master clock not found in path context."
` );
` status = SOS_Error;
` }
` }
`
` return status;
`}
`
`Page 20 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/clocksync.c
`Page 21/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
`901
`902
`903
`904
`905
`906
`907
`908
`909
`910
`911
`912
`913
`914
`915
`916
`917
`918
`919
`920
`921
`922
`923
`924
`925
`926
`927
`928
`929
`930
`931
`932
`933
`934
`935
`936
`937
`938
`939
`940
`941
`942
`943
`944
`945
`
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`Bead init and uninit
`+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
`
`/*++
`Routine Name:
`
` ClockSync_BeadInit
`
`Routine Description:
`
`Parameters:
`
` SOS_BEAD *Bead - [in]
` A reference to the timesync bead. We use this parameter to
` register edges assocated with the bead.
`
` SOS_REGOBJECT *InitContext - [in]
` Set to the value passed into the bead register function (NULL).
`
`Return Value:
`
` SOS_STATUS -
` The return value of our call to SOS_Edge_Register.
`
`--*/
`static
`SOS_STATUS
`ClockSync_BeadInit(
` SOS_BEAD *Bead,
` SOS_REGOBJECT *InitContext
`)
`{
` SOS_STATUS status;
`
` SOS_DEBUGOUT_FUNC_TRACE("BeadInit called\n");
`
` status = SOS_Edge_Register(
` Bead,
` "Encode",
` NULL,
` NULL,
` NULL,
`
`Page 21 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/clocksync.c
`Page 22/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
` ClockSync_KeyCreate,
` ClockSync_EncodeHandler,
` NULL,
` NULL,
` ClockSync_PathInit,
` NULL);
`
` if (SOS_FAILED(status)) {
` SOS_DEBUGOUT_MAJOR_EVENT( "Could not register edge");
` }
`
` status = SOS_Edge_Register(
` Bead,
` "Decode",
` NULL,
` NULL,
` NULL,
` ClockSync_KeyCreate,
` ClockSync_DecodeHandler,
` NULL,
` NULL,
` ClockSync_PathInit,
` NULL);
`
` if (SOS_FAILED(status)) {
` SOS_DEBUGOUT_MAJOR_EVENT( "Could not register edge");
` }
`
` status = SOS_Edge_Register(
` Bead,
` "MasterEncode",
` NULL,
` NULL,
` NULL,
` ClockSync_KeyCreate,
` ClockSync_MasterEncodeHandler,
` NULL,
` NULL,
` NULL,
` NULL);
`
` if (SOS_FAILED(status)) {
` SOS_DEBUGOUT_MAJOR_EVENT( "Could not register edge");
` }
`
`946
`947
`948
`949
`950
`951
`952
`953
`954
`955
`956
`957
`958
`959
`960
`961
`962
`963
`964
`965
`966
`967
`968
`969
`970
`971
`972
`973
`974
`975
`976
`977
`978
`979
`980
`981
`982
`983
`984
`985
`986
`987
`988
`989
`990
`
`Page 22 of 26
`
`Implicit Exhibit 2087
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.15/b…/…/main/clocksync.c
`Page 23/26
`Saved: 11/8/01, 8:46:36 PM
`Printed for: Implicit
`
` status = SOS_Edge_Register(
` Bead,
` "Master",
` NULL,
` NULL,
` NULL,
` ClockSync_KeyCreate,
` NULL, /* NOTE - no handler */
` NULL,
` NULL,
` ClockSync_MasterPathInit,
` NULL);
`
` if (SOS_FAILED(status)) {
` SOS_DEBUGOUT_MAJOR_EVENT( "Could not register edge");
` }
`
` status = SOS_Bead_SchemaSet(Bead, "clocksync");
`
` if (SOS_FAILED(status)) {
` SOS_DEBUGOUT_MAJOR_EVENT( "Could not set bead schema");
` }
`
` return status;
`}
`
`/*++
`Routine Name:
`
` ClockSync_BeadUninit
`
`Routine Description:
`
` Called when Strings attempts to unload the Bead.
`
`Parameters:
`
` void *BeadContext - [in]
` NULL because SOS_Bead_ContextPut is never called by this bead.
`
`Return