`Page 1/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`1
`++++++¬
`…
`¬2
`Copyright (c) 2001 BeComm Corporation¬
`3
`¬4
`Filename:¬
`5
`¬6
` timesync.c¬
`7
`¬8
`Group Name:¬
`9
`¬10
` todo¬
`11
`¬12
`Group Overview:¬
`13
`¬14
` Uses a broadcast protocol to determine the¬
`15
` clock offsets of all listening peers.¬
`16
`¬17
` Algorithm is based loosely on NTP.¬
`18
`¬19
` Also has edges which are used for passing¬
`20
` sample clocks across the network in a path.¬
`21
`¬22
`Owner:¬
`23
`¬24
` Guy Carpenter (guyc) 16-Aug-2001¬
`25
`¬26
`-------------------------------------------------------------------------
`27
`----*/¬
`…
`#define SOS_DEBUG_ZONE "/beads/timesync"¬
`28
`#include <sosstrings.h>¬
`29
`#include <sosmultimedia.h>¬
`30
`#include "timesync.h"¬
`31
`¬32
`SOS_SOURCE_VERSION("$Id: timesync.c,v 1.14 2001/10/23 16:40:49 guyc Exp
`33
`$");¬
`…
`¬34
`/*¬
`35
`* Broadcast sync packets every TIMER_INTERVAL milliseconds¬
`36
`*/¬
`37
`#define TIMER_INTERVAL 4000¬
`38
`#define TIMER_INITIAL_DELAY 200¬
`39
`#define MAX_AGE
`60000 /* expire after a minute */¬
`40
`¬41
`/*¬
`42
`
`Page 1 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/bea…/…/main/timesync.c
`Page 2/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
` * Compute offset based on WINDOW_SIZE observations¬
`43
` */¬
`44
`#define WINDOW_SIZE 8¬
`45
`¬46
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`47
`++++++¬
`…
`Named Constants¬
`48
`-------------------------------------------------------------------------
`49
`----*/¬
`…
`¬50
`/*¬
`51
` * Name of bead¬
`52
` */¬
`53
`static¬
`54
`const char BEAD_NAME[] = "timesync";¬
`55
`¬56
`¬57
`¬58
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`59
`++++++¬
`…
`Globals¬
`60
`-------------------------------------------------------------------------
`61
`----*/¬
`…
`¬62
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`63
`++++++¬
`…
`Structs¬
`64
`-------------------------------------------------------------------------
`65
`----*/¬
`…
`¬66
`typedef struct {¬
`67
` SOS_UINT32 HostId;¬
`68
` SOS_CLOCK_TICK XmitTime;¬
`69
` SOS_CLOCK_TICK RecvTime;¬
`70
` SOS_INT32 Offset;¬
`71
` SOS_BOOLEAN OffsetValid;¬
`72
` SOS_INT32 Min[WINDOW_SIZE];¬
`73
` SOS_INT32 Max[WINDOW_SIZE];¬
`74
` SOS_UINT32 WindowFill;¬
`75
` SOS_UINT32 WindowPtr;¬
`76
`} HOSTINFO;¬
`77
`¬78
`typedef struct _UPDATE_HEADER {¬
`79
` SOS_UINT32 HostId;¬
`80
` SOS_CLOCK_TICK XmitTime;¬
`81
`
`Page 2 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/bea…/…/main/timesync.c
`Page 3/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`} UPDATE_HEADER;¬
`82
`¬83
`typedef struct {¬
`84
` SOS_UINT32 HostId;¬
`85
` SOS_CLOCK_TICK XmitTime;¬
`86
` SOS_CLOCK_TICK RecvTime;¬
`87
`} HOSTSYNC;¬
`88
`¬89
`typedef struct UPDATE_CONTEXT {¬
`90
` SOS_POINTERTABLE * HostTable;¬
`91
` SOS_LOCK * HostTableLock;¬
`92
` SOS_UINT32 HostId;¬
`93
` SOS_PATH * Path;¬
`94
` SOS_TIMER_ID TimerId;¬
`95
`} UPDATE_CONTEXT;¬
`96
`¬97
`#define LOCK() SOS_Lock_Acquire(g_Context->HostTableLock)¬
`98
`#define UNLOCK() SOS_Lock_Release(g_Context->HostTableLock)¬
`99
`¬
`100
`¬
`101
`/*¬
`102
` * Maintain a single global context, since this is a system-wide
`103
`protocol.¬
`…
` */¬
`104
`static¬
`105
`UPDATE_CONTEXT * g_Context;¬
`106
`¬
`107
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`108
`++++++¬
`…
`¬
`109
`-------------------------------------------------------------------------
`110
`----*/¬
`…
`¬
`111
`static¬
`112
`HOSTINFO *¬
`113
`TimeSync_HostInfoFind(¬
`114
` SOS_UINT32 HostId¬
`115
`)¬
`116
`{¬
`117
` HOSTINFO *host = NULL;¬
`118
`¬
`119
` SOS_PointerTable_ElementPeek(¬
`120
` g_Context->HostTable,¬
`121
` (void*)HostId,¬
`122
` (void**)&host¬
`123
`
`Page 3 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/bea…/…/main/timesync.c
`Page 4/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`124
`125
`126
`127
`128
`129
`130
`131
`132
`133
`134
`135
`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
`
` );¬
`¬
` return host;¬
`}¬
`static¬
`HOSTINFO *¬
`TimeSync_HostInfoFindOrAdd(¬
` SOS_UINT32 HostId¬
`)¬
`{¬
` HOSTINFO *host = NULL;¬
`¬
` host = TimeSync_HostInfoFind(HostId);¬
`¬
` if (!host) {¬
` SOS_DEBUGOUT_MAJOR_EVENT(¬
` "Adding host %x to table\n",¬
` HostId¬
` );¬
` host = SOS_Mem_Alloc(sizeof(*host));¬
` SOS_memset(host, 0, sizeof(*host));¬
` host->HostId = HostId;¬
` SOS_PointerTable_ElementPut(¬
` g_Context->HostTable,¬
` (void*)HostId,¬
` host¬
` );¬
` }¬
`¬
` return host;¬
`}¬
`¬
`static¬
`void¬
`TimeSync_Expire(¬
` UPDATE_CONTEXT * Context,¬
` SOS_UINT32 MaxAge¬
`)¬
`{¬
`¬
` SOS_POINTERTABLE_ITERATOR *iterator;¬
` HOSTINFO *hostInfo;¬
` SOS_CLOCK_TICK now = SOS_Clock_TickGet();¬
` ¬
` SOS_DEBUGOUT_FUNC_TRACE("TimeSync_Expire\n");¬
`
`Page 4 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/bea…/…/main/timesync.c
`Page 5/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`169
`170
`171
`172
`173
`174
`175
`176
`177
`178
`179
`180
`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
`
`¬
` LOCK();¬
`¬
` SOS_PointerTableIterator_Create(¬
` Context->HostTable,¬
` &iterator¬
` );¬
`¬
` while (SOS_Success==SOS_PointerTableIterator_Next(¬
` iterator,¬
` NULL,¬
` (void**)&hostInfo¬
` )) {¬
` SOS_CLOCK_TICK age = now - hostInfo->RecvTime;¬
`¬
` if (age>MaxAge) {¬
`¬
` SOS_DEBUGOUT_MAJOR_EVENT(¬
` "Removing host %x (age %lu) from table\n",¬
` hostInfo->HostId,¬
` age¬
` );¬
` ¬
` SOS_PointerTable_ElementRemove(¬
` Context->HostTable,¬
` (void*)hostInfo->HostId,¬
` NULL¬
` );¬
`¬
` {¬
` /*¬
` * This ugliness works around the fact¬
` * that the table API does not allow us¬
` * to destroy a member during iteration.¬
` * So each time we remove something we¬
` * start again.¬
` */¬
` SOS_PointerTableIterator_Destroy(¬
` iterator¬
` );¬
` SOS_PointerTableIterator_Create(¬
` Context->HostTable,¬
` &iterator¬
` );¬
` }¬
`
`Page 5 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/bea…/…/main/timesync.c
`Page 6/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`214
`215
`216
`217
`218
`219
`220
`221
`222
`223
`224
`225
`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
`
` }¬
` }¬
`¬
` SOS_PointerTableIterator_Destroy(¬
` iterator¬
` );¬
`¬
` UNLOCK();¬
`¬
`}¬
`¬
`static¬
`void¬
`TimeSync_HostUpdate(¬
` SOS_UINT32 HostId,¬
` SOS_CLOCK_TICK XmitTime,¬
` SOS_CLOCK_TICK RecvTime,¬
` HOSTSYNC * HostSync¬
`)¬
`{¬
` HOSTINFO *info;¬
`¬
` LOCK();¬
`¬
` info = TimeSync_HostInfoFindOrAdd(HostId);¬
`¬
` info->XmitTime = XmitTime;¬
` info->RecvTime = RecvTime;¬
`¬
` if (HostSync) {¬
` /*¬
` * Consider the offset td between host A and host B.¬
` * t0 the packet was sent by A¬
` * t1 the packet was received by B¬
` * t2 response sent by B¬
` * t3 response received by A¬
` * delayAB is the real time delay between event0 and event1¬
` * delayBA is the real time delay between event2 and event3¬
` * td is the clock offset such that (t0+td==t1)¬
` * ¬
` * t0+td+delayAB = t1¬
` * t2-td+delayBA = t3¬
` *¬
` * td = t1-t0-delayAB¬
` * td = t2-t3+delayBA¬
`
`Page 6 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/bea…/…/main/timesync.c
`Page 7/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`259
`260
`261
`262
`263
`264
`265
`266
`267
`268
`269
`270
`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
`
` *¬
` * Since delayAB and delayBA are always >= 0¬
` * td <= (t1-t0)¬
` * td >= (t2-t3)¬
` *¬
` * This gives us a way of computing bounds on td. We¬
` * expect delayAB and delayBA to vary rapidly, but td¬
` * to vary very slowly (only as the clocks drift relative¬
` * to each other).¬
` */¬
` SOS_UINT32 t0 = HostSync->XmitTime;¬
` SOS_UINT32 t1 = HostSync->RecvTime;¬
` SOS_UINT32 t2 = XmitTime;¬
` SOS_UINT32 t3 = RecvTime;¬
` SOS_INT32 tdmax = (SOS_INT32)(t1-t0);¬
` SOS_INT32 tdmin = (SOS_INT32)(t2-t3);¬
`¬
` /*¬
` * Instantanous offset value would be¬
` * info->Offset = ((SOS_INT32)((t1-t0)+(t2-t3)))/2;¬
` * but we will keep a running average of min and max to¬
` * smooth out asymmetric delivery delays.¬
` */¬
` if (0) {¬
` SOS_Debug_StringPrint(¬
` "%lu %lu %lu %lu\n",¬
` t0,¬
` t1,¬
` t2,¬
` t3¬
` );¬
` }¬
` ¬
` /*¬
` * Store values for running min/max¬
` */¬
` info->Min[info->WindowPtr] = tdmin;¬
` info->Max[info->WindowPtr] = tdmax;¬
` info->WindowPtr++;¬
` if (info->WindowFill<info->WindowPtr) {¬
` info->WindowFill = info->WindowPtr;¬
` }¬
` if (info->WindowPtr==WINDOW_SIZE) {¬
` info->WindowPtr=0;¬
` }¬
`
`Page 7 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/bea…/…/main/timesync.c
`Page 8/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`304
`305
`306
`307
`308
`309
`310
`311
`312
`313
`314
`315
`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
`
`¬
` /*¬
` * Now compute an estimate for offset¬
` */¬
` {¬
` SOS_INT32 min = tdmin;¬
` SOS_INT32 max = tdmax;¬
` SOS_UINT32 i;¬
` for (i=0;i<info->WindowFill;i++) {¬
` /*¬
` * note this is finding the highest min¬
` * and lowest max.¬
` */¬
` if (info->Min[i]>min) min=info->Min[i];¬
` if (info->Max[i]<max) max=info->Max[i];¬
` }¬
` /*¬
` * Use¬
` * M = A+(B-A)/2¬
` * instead of¬
` * M = (A+B)/2¬
` * to avoid overflow - A+B might exceed maxval.¬
` */¬
` info->Offset = min+(max-min)/2;¬
` info->OffsetValid = SOS_True;¬
`¬
` if (0) {¬
` for (i=0;i<info->WindowFill;i++) {¬
` SOS_Debug_StringPrint("%ld ",info->Min[i]);¬
` }¬
` SOS_Debug_StringPrint("\n");¬
` for (i=0;i<info->WindowFill;i++) {¬
` SOS_Debug_StringPrint("%ld ",info->Max[i]);¬
` }¬
` SOS_Debug_StringPrint("\n");¬
` }¬
`¬
` if (0) {¬
` SOS_Debug_StringPrint(¬
` "Offset for %x= now %ld/%ld/%ld smooth
`%ld/%ld/%ld\n",¬
` HostId,¬
` tdmin,¬
` tdmin+(tdmax-tdmin)/2,¬
` tdmax,¬
`
`Page 8 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/bea…/…/main/timesync.c
`Page 9/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`348
`349
`350
`351
`352
`353
`354
`355
`356
`357
`358
`359
`360
`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
`
` min,¬
` min+(max-min)/2,¬
` max¬
` );¬
` }¬
` }¬
`¬
` }¬
` ¬
` UNLOCK();¬
`}¬
` ¬
`¬
`SOS_STATUS¬
`TimeSync_OffsetGet(¬
` SOS_UINT32 HostId,¬
` SOS_CLOCK_TICK * Offset¬
` ¬
`)¬
`{¬
` SOS_STATUS status = SOS_Success;¬
` HOSTINFO *hostInfo;¬
` SOS_UINT32 offset = 0;¬
` ¬
` LOCK();¬
` ¬
` hostInfo = TimeSync_HostInfoFind(HostId);¬
` ¬
` if (hostInfo && hostInfo->OffsetValid) {¬
` offset = hostInfo->Offset;¬
` } else {¬
` status = SOS_ErrorNotFound;¬
` }¬
`¬
` if (Offset) {¬
` *Offset = offset;¬
` }¬
`¬
` UNLOCK();¬
` return status;¬
`}¬
`¬
`SOS_STATUS¬
`TimeSync_HostIdGet(¬
` SOS_UINT32 * HostId¬
`
`Page 9 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/be…/…/main/timesync.c
`Page 10/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`393
`394
`395
`396
`397
`398
`399
`400
`401
`…
`402
`403
`…
`404
`405
`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
`
`)¬
`{¬
` *HostId = g_Context->HostId;¬
` return SOS_Success;¬
`}¬
`¬
`¬
`¬
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`++++++¬
`Context create and destory¬
`-------------------------------------------------------------------------
`----*/¬
`¬
`/*++¬
`Routine Name:¬
`¬
` TimeSync_ContextCreate¬
`¬
`Routine Description:¬
`¬
` Attempt to allocate a TimeSync 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¬
`UPDATE_CONTEXT *¬
`TimeSync_ContextCreate(¬
` void¬
`)¬
`{¬
` UPDATE_CONTEXT *context;¬
`¬
` SOS_DEBUGOUT_FUNC_TRACE("TimeSync_ContextCreate called\n");¬
`
`Page 10 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/be…/…/main/timesync.c
`Page 11/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`435
`436
`437
`438
`439
`440
`441
`442
`443
`444
`445
`446
`447
`448
`449
`450
`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
`
`¬
` /* allocate memory for TimeSync session context */¬
` context = SOS_Mem_Alloc(sizeof(*context));¬
`¬
` if (context) {¬
` context->HostTable = SOS_PointerTable_Create(¬
` NULL, /* generate hash from key pointer */¬
` NULL, /* use pointer equality for key compare */¬
` NULL, /* no key freeproc */¬
` SOS_Mem_Free /* element freeproc */¬
` );¬
` context->HostTableLock = SOS_Lock_Create();¬
` context->HostId = SOS_Clock_TickGet();¬
` }¬
` return context;¬
`}¬
`¬
`/*++¬
`Routine Name:¬
`¬
` TimeSync_ContextDestroy¬
`¬
`Routine Description:¬
`¬
` A helper function use to release all TimeSync context resources.¬
`¬
`Parameters:¬
`¬
` UPDATE_CONTEXT * Context - [consumed]¬
` An TimeSync context who's resources and memory are to be freed¬
`¬
`Return Value:¬
`¬
` None.¬
`¬
`--*/¬
`static¬
`void¬
`TimeSync_ContextDestroy(¬
` UPDATE_CONTEXT * Context¬
`)¬
`{¬
` SOS_DEBUGOUT_FUNC_TRACE("TimeSync_ContextDestroy called\n");¬
` ¬
` if (Context) {¬
`
`Page 11 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/be…/…/main/timesync.c
`Page 12/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`480
`481
`482
`483
`484
`485
`486
`487
`…
`488
`489
`…
`490
`491
`492
`493
`494
`495
`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
`
` SOS_Path_Destroy(Context->Path);¬
` SOS_PointerTable_Destroy(Context->HostTable);¬
` SOS_Lock_Destroy(Context->HostTableLock);¬
` SOS_Mem_Free(Context);¬
` }¬
`}¬
`¬
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`++++++¬
`Broadcast¬
`-------------------------------------------------------------------------
`----*/¬
`static¬
`SOS_STATUS¬
`TimeSync_PathCreate(¬
` UPDATE_CONTEXT * Context¬
`)¬
`{¬
` SOS_STATUS status;¬
`#define OUTPUT_CONTENT_TYPE "TimeSync/Output"¬
` SOS_REGOBJECT *contentType =¬
` SOS_String_CreateFromString(OUTPUT_CONTENT_TYPE);¬
`¬
` Context->Path = SOS_Path_Create(NULL /* no parent path */);¬
` if (Context->Path) {¬
` status = SOS_Path_AttributeSet(¬
` Context->Path,¬
` "Content-Type",¬
` contentType¬
` );¬
` } else {¬
` /* couldn't create path */¬
` status = SOS_Error;¬
` }¬
`¬
` SOS_RegObject_Release(contentType);¬
`¬
` return status;¬
`}¬
`¬
`¬
`static¬
`SOS_STATUS¬
`TimeSync_Send(¬
` UPDATE_CONTEXT * Context¬
`
`Page 12 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/be…/…/main/timesync.c
`Page 13/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`523
`524
`525
`526
`527
`528
`529
`530
`531
`532
`533
`534
`535
`536
`537
`538
`539
`540
`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
`
`)¬
`{¬
` SOS_STATUS status;¬
` SOS_MESSAGE *message = SOS_Message_Create();¬
` UPDATE_HEADER *header;¬
` HOSTSYNC *hostSync, *nextSync;¬
` HOSTINFO *hostInfo;¬
` SOS_CLOCK_TICK now = SOS_Clock_TickGet();¬
` SOS_UINT32 count, validCount;¬
` SOS_POINTERTABLE_ITERATOR *iterator;¬
`¬
` SOS_DEBUGOUT_FUNC_TRACE("TimeSync_Send\n");¬
`¬
` LOCK();¬
`¬
` count = SOS_PointerTable_LengthGet(¬
` Context->HostTable¬
` );¬
` validCount=0;¬
`¬
` hostSync = SOS_Mem_Alloc(sizeof(HOSTSYNC)*count);¬
` nextSync = hostSync;¬
` ¬
` SOS_PointerTableIterator_Create(¬
` Context->HostTable,¬
` &iterator¬
` );¬
`¬
` while (SOS_Success==SOS_PointerTableIterator_Next(¬
` iterator,¬
` NULL,¬
` (void**)&hostInfo¬
` )) {¬
` SOS_CLOCK_TICK age = now - hostInfo->RecvTime;¬
`¬
` SOS_Debug_StringPrint(¬
` "Host %x age %lu offset %ld\n",¬
` hostInfo->HostId,¬
` age,¬
` hostInfo->Offset¬
` );¬
`¬
` nextSync->HostId = hostInfo->HostId;¬
` nextSync->XmitTime = hostInfo->XmitTime;¬
` nextSync->RecvTime = hostInfo->RecvTime;¬
`
`Page 13 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/be…/…/main/timesync.c
`Page 14/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`568
`569
`570
`571
`572
`573
`574
`575
`576
`577
`578
`579
`580
`581
`582
`583
`584
`585
`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
`
` nextSync++;¬
` validCount++;¬
` }¬
`¬
` SOS_PointerTableIterator_Destroy(¬
` iterator¬
` );¬
`¬
` UNLOCK();¬
`¬
` SOS_Message_HeadDataPush(¬
` message,¬
` hostSync,¬
` sizeof(HOSTSYNC)*validCount,¬
` SOS_Mem_Free¬
` );¬
`¬
` header = SOS_Mem_Alloc(sizeof(*header));¬
` /* set this as late as possible */¬
` header->HostId = Context->HostId;¬
` header->XmitTime = SOS_Clock_TickGet();¬
` SOS_Message_HeadDataPush(¬
` message,¬
` header,¬
` sizeof(*header),¬
` SOS_Mem_Free¬
` );¬
`¬
` ¬
` status = SOS_Path_MessageSend(¬
` Context->Path,¬
` message¬
` );¬
`¬
` return status;¬
`}¬
`static¬
`void¬
`TimeSync_CallBack(¬
` void * Context¬
`);¬
`¬
`static¬
`SOS_STATUS¬
`TimeSync_TimerStart(¬
`
`Page 14 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/be…/…/main/timesync.c
`Page 15/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`613
`614
`615
`616
`617
`618
`619
`620
`621
`622
`623
`624
`625
`626
`627
`628
`629
`630
`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
`
` UPDATE_CONTEXT * Context¬
`)¬
`{¬
` SOS_STATUS status;¬
` SOS_DEBUGOUT_FUNC_TRACE("TimeSync_TimerStart\n");¬
`¬
` status = SOS_Timer_PeriodicSchedule(¬
` TIMER_INITIAL_DELAY,¬
` TIMER_INTERVAL,¬
` TimeSync_CallBack,¬
` Context,¬
` &Context->TimerId¬
` );¬
`¬
` return status;¬
`}¬
`¬
`static¬
`SOS_STATUS¬
`TimeSync_TimerStop(¬
` UPDATE_CONTEXT * Context¬
`)¬
`{¬
` SOS_STATUS status;¬
` SOS_DEBUGOUT_FUNC_TRACE("TimeSync_TimerStop\n");¬
`¬
` status = SOS_Timer_Cancel(¬
` Context->TimerId¬
` );¬
`¬
` return status;¬
`}¬
`¬
`static¬
`void¬
`TimeSync_CallBack(¬
` void * Context¬
`)¬
`{¬
` SOS_DEBUGOUT_FUNC_TRACE("TimeSync_TimerCallBack\n");¬
` TimeSync_Expire(Context, MAX_AGE);¬
` TimeSync_Send(Context);¬
`}¬
`¬
`¬
`
`Page 15 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/be…/…/main/timesync.c
`Page 16/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`658
`…
`659
`660
`…
`661
`662
`663
`664
`665
`666
`667
`668
`669
`670
`671
`672
`673
`674
`675
`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
`
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`++++++¬
`Edge Handlers¬
`-------------------------------------------------------------------------
`----*/¬
`¬
`/*++¬
`Routine Name:¬
`¬
` TimeSync_KeyCreate¬
`¬
`Routine Description:¬
`¬
` To ensure a single session, the key is constant.¬
`¬
`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¬
`TimeSync_KeyCreate(¬
` SOS_PATH *Path,¬
` SOS_MESSAGE *Message¬
`)¬
`{¬
`#define KEY_STRING "timesync key"¬
` SOS_REGOBJECT* key;¬
` SOS_STATUS status;¬
`¬
` SOS_DEBUGOUT_FUNC_TRACE("TimeSync_KeyCreate called\n");¬
`¬
` status = SOS_RegObject_CreateFromString(KEY_STRING, &key);¬
`¬
` if (SOS_SUCCEEDED(status)) {¬
`
`Page 16 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/be…/…/main/timesync.c
`Page 17/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`701
`702
`703
`704
`705
`706
`707
`708
`709
`710
`711
`712
`713
`714
`715
`716
`717
`718
`719
`720
`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
`
` status = SOS_Path_SessionKeySet(Path, key);¬
` }¬
`¬
` SOS_RegObject_Release(key);¬
`¬
` return SOS_SUCCEEDED(status) ? SOS_PathBuild_Stop : status;¬
`}¬
`¬
`¬
`/*++¬
`Routine Name:¬
`¬
` TimeSync_UpdateHandler¬
`¬
`Routine Description:¬
`¬
` Insert Description Here¬
`¬
`Parameters:¬
`¬
` SOS_PATH *Path - [in]¬
` The Path that this message is arriving on. It is used to get¬
` the TimeSync session context.¬
`¬
` SOS_MESSAGE *Message - [consumed]¬
` Message containing timesync data to be decoded.¬
`¬
`Return Value:¬
`¬
` SOS_STATUS - ¬
` SOS_Success¬
` if the data was successfuly decoded.¬
`¬
` SOS_Error otherwise.¬
`¬
`--*/¬
`static¬
`SOS_STATUS¬
`TimeSync_UpdateHandler(¬
` SOS_PATH *Path,¬
` SOS_MESSAGE *Message¬
`)¬
`{¬
` SOS_STATUS status = SOS_Success;¬
` SOS_CLOCK_TICK recvTime = SOS_Clock_TickGet();¬
`
`Page 17 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/be…/…/main/timesync.c
`Page 18/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`746
`747
`748
`749
`750
`751
`752
`753
`754
`755
`756
`757
`758
`759
`760
`761
`762
`763
`764
`765
`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
`
` UPDATE_CONTEXT * context;¬
` HOSTSYNC hostSync;¬
` UPDATE_HEADER header;¬
` SOS_BOOLEAN found = SOS_False;¬
`¬
` status = SOS_Path_SessionContextPeek(Path, (void**)&context);¬
`¬
` SOS_Message_HeadDataPop(¬
` Message,¬
` sizeof(UPDATE_HEADER),¬
` &header,¬
` NULL¬
` );¬
`¬
`¬
` if (0) {¬
` SOS_Debug_StringPrint(¬
` "Received TimeSync from %x@%lu\n",¬
` header.HostId,¬
` header.XmitTime¬
` );¬
` }¬
`¬
`// SOS_ASSERT_ASSUMPTION(0,"break");¬
`¬
`// if (header.HostId!=context->HostId) {¬
` if (1) {¬
` while (!found &&¬
` SOS_Message_LengthGet(Message)>=sizeof(HOSTSYNC)) {¬
` SOS_Message_HeadDataPop(¬
` Message,¬
` sizeof(HOSTSYNC),¬
` &hostSync,¬
` NULL¬
` );¬
`¬
` if (0) {¬
` SOS_Debug_StringPrint(¬
` "TimeSync from %x@%lu contains %x@%lu/%lu\n",¬
` header.HostId,¬
` header.XmitTime,¬
` hostSync.HostId,¬
` hostSync.XmitTime,¬
` hostSync.RecvTime¬
` );¬
`
`Page 18 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/be…/…/main/timesync.c
`Page 19/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`791
`792
`793
`794
`795
`796
`797
`798
`799
`800
`801
`802
`803
`804
`805
`806
`807
`808
`809
`810
`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
`
` }¬
` ¬
` if (hostSync.HostId==context->HostId) {¬
` found = SOS_True;¬
` }¬
` }¬
`¬
` TimeSync_HostUpdate(¬
` header.HostId,¬
` header.XmitTime,¬
` recvTime,¬
` found ? &hostSync : NULL¬
` );¬
` }¬
`¬
` SOS_Message_Destroy(Message);¬
` ¬
` SOS_DEBUGOUT_FUNC_TRACE("TimeSync_UpdateHandler\n");¬
`¬
`// SOS_ASSERT_ASSUMPTION(0,"break");¬
`¬
` if (0) {¬
` SOS_REGOBJECT *localAddress;¬
` SOS_REGOBJECT *remoteAddress;¬
` char *localString;¬
` char *remoteString;¬
`¬
` SOS_Path_AttributeGet(¬
` Path,¬
` "Network-Address-Local",¬
` &localAddress¬
` );¬
` SOS_Path_AttributeGet(¬
` Path,¬
` "Network-Address-Remote",¬
` &remoteAddress¬
` );¬
`¬
` SOS_RegObject_ToQualifiedString(¬
` localAddress,¬
` &localString¬
` );¬
`¬
` SOS_RegObject_ToQualifiedString(¬
` localAddress,¬
`
`Page 19 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/be…/…/main/timesync.c
`Page 20/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`836
`837
`838
`839
`840
`841
`842
`843
`844
`845
`846
`847
`848
`849
`850
`851
`852
`853
`854
`855
`856
`857
`858
`…
`859
`860
`…
`861
`862
`863
`864
`865
`866
`867
`868
`869
`870
`871
`872
`873
`874
`875
`876
`877
`878
`
` &remoteString¬
` );¬
`¬
` SOS_Debug_StringPrint(¬
` "LocalAddress=%s RemoteAddress=%s\n",¬
` localString,¬
` remoteString¬
` );¬
`¬
`// SOS_ASSERT_ASSUMPTION(0,"break");¬
`¬
` SOS_Mem_Free(localString);¬
` SOS_Mem_Free(remoteString);¬
` }¬
`¬
`// SOS_Debug_StringPrint("TimeSync update handler hit\n");¬
`¬
` return status;¬
`}¬
`¬
`¬
`¬
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`++++++¬
`Session init and uninit¬
`+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`++++*/¬
`¬
`/*++¬
`Routine Name:¬
`¬
` TimeSync_SessionInit¬
`¬
`Routine Description:¬
`¬
` Called by Strings when TimeSync_KeyCreate returns that a new¬
` TimeSync 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 mp3decoder to be created.¬
`¬
`Return Value:¬
`
`Page 20 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/be…/…/main/timesync.c
`Page 21/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`879
`880
`881
`882
`883
`884
`885
`886
`887
`888
`889
`890
`891
`892
`893
`894
`895
`896
`897
`898
`899
`900
`901
`902
`903
`904
`905
`906
`907
`908
`909
`910
`911
`912
`913
`914
`915
`916
`917
`918
`919
`920
`921
`922
`923
`
`¬
` SOS_STATUS - ¬
` SOS_Success if a context was created and succesfully assocated¬
` with a path.¬
`¬
` SOS_Error otherwise.¬
`¬
`--*/¬
`static¬
`SOS_STATUS¬
`TimeSync_SessionInit(¬
` SOS_PATH *Path¬
`)¬
`{¬
` SOS_STATUS status = SOS_Success;¬
` UPDATE_CONTEXT *context = g_Context;¬
`¬
` SOS_DEBUGOUT_FUNC_TRACE("TimeSync_SessionInit called\n");¬
` ¬
` if (context) {¬
` /* assocate the new context with a path */¬
` status = SOS_Path_SessionContextPut(Path, context);¬
` } else {¬
` status = SOS_ErrorResourceAllocation;¬
` }¬
`¬
` return status;¬
`}¬
`¬
`/*++¬
`Routine Name:¬
`¬
` TimeSync_SessionUninit¬
`¬
`Routine Description:¬
`¬
` Called by Strings to free all memory assocated with this session¬
` of mp3decoder.¬
`¬
`Parameters:¬
`¬
` SOS_PATH *Path - [in]¬
` The path assocated with the mp3decoder to be destroyed.¬
`¬
`Return Value:¬
`
`Page 21 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/be…/…/main/timesync.c
`Page 22/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`924
`925
`926
`927
`928
`929
`930
`931
`932
`933
`934
`935
`936
`937
`938
`939
`940
`941
`942
`943
`944
`945
`946
`947
`948
`949
`950
`951
`952
`953
`954
`955
`956
`…
`957
`958
`…
`959
`960
`961
`962
`963
`964
`965
`966
`
`¬
` SOS_STATUS - ¬
` SOS_Success¬
` on successful uninit.¬
`¬
` SOS_Error¬
` if the context could not be retrieved.¬
`¬
`--*/¬
`static¬
`SOS_STATUS¬
`TimeSync_SessionUninit(¬
` SOS_PATH *Path¬
`)¬
`{¬
` SOS_STATUS status;¬
` UPDATE_CONTEXT *context;¬
`¬
` SOS_DEBUGOUT_FUNC_TRACE("TimeSync_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 */¬
` if (SOS_SUCCEEDED(status) && context) {¬
` // don't destroy it, it's global.¬
`// TimeSync_ContextDestroy(context);¬
` }¬
`¬
` return status;¬
`}¬
`¬
`/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`++++++¬
`Bead init and uninit¬
`+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`++++*/¬
`¬
`/*++¬
`Routine Name:¬
`¬
` TimeSync_BeadInit¬
`¬
`Routine Description:¬
`¬
`
`Page 22 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/be…/…/main/timesync.c
`Page 23/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`967
`968
`969
`970
`971
`972
`973
`974
`975
`976
`977
`978
`979
`980
`981
`982
`983
`984
`985
`986
`987
`988
`989
`990
`991
`992
`993
`994
`995
`996
`997
`998
`999
`1000
`1001
`1002
`1003
`1004
`1005
`1006
`1007
`1008
`1009
`1010
`1011
`
`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¬
`TimeSync_BeadInit(¬
` SOS_BEAD *Bead,¬
` SOS_REGOBJECT *InitContext¬
`)¬
`{¬
` SOS_STATUS status;¬
`¬
` SOS_DEBUGOUT_FUNC_TRACE("BeadInit called\n");¬
` /* register Sync Edge */¬
` status = SOS_Edge_Register(¬
` Bead,¬
` "Update",¬
` NULL,¬
` NULL,¬
` NULL,¬
` TimeSync_KeyCreate,¬
` TimeSync_UpdateHandler,¬
` NULL,¬
` NULL,¬
` NULL,¬
` NULL);¬
`¬
` if (SOS_FAILED(status)) {¬
` SOS_DEBUGOUT_MAJOR_EVENT( "Could not register Decode edge");¬
` }¬
`¬
` g_Context = TimeSync_ContextCreate();¬
` ¬
`
`Page 23 of 27
`
`Implicit Exhibit 2019
`Sonos v. Implicit, IPR2018-0766, -0767
`
`
`
`/Users/implicit/Desktop/Source Code/2001.11.01/be…/…/main/timesync.c
`Page 24/27
`Saved: 10/23/01, 11:40:49 AM
`Printed for: Implicit
`
`1012
`1013
`1014
`1015
`1016
`1017
`1018
`1019
`1020
`1021
`1022
`1023
`1024
`1025
`1026
`1027
`1028
`1029
`1030
`1031
`1032
`1033
`1034
`1035
`1036
`1037
`1038
`1039
`1040
`1041
`1042
`1