| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -8,6 +8,7 @@ import ( | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						"path/filepath" | 
					 | 
					 | 
					 | 
						"path/filepath" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						"sort" | 
					 | 
					 | 
					 | 
						"sort" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						"strings" | 
					 | 
					 | 
					 | 
						"strings" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						"sync" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						"time" | 
					 | 
					 | 
					 | 
						"time" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						"github.com/owncast/owncast/core/data" | 
					 | 
					 | 
					 | 
						"github.com/owncast/owncast/core/data" | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -26,26 +27,29 @@ import ( | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// S3Storage is the s3 implementation of a storage provider.
 | 
					 | 
					 | 
					 | 
					// S3Storage is the s3 implementation of a storage provider.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					type S3Storage struct { | 
					 | 
					 | 
					 | 
					type S3Storage struct { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						sess     *session.Session | 
					 | 
					 | 
					 | 
						// If we try to upload a playlist but it is not yet on disk
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						// then keep a reference to it here.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						queuedPlaylistUpdates map[string]string | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						s3Client *s3.S3 | 
					 | 
					 | 
					 | 
						s3Client *s3.S3 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						uploader *s3manager.Uploader | 
					 | 
					 | 
					 | 
						uploader *s3manager.Uploader | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// If we try to upload a playlist but it is not yet on disk
 | 
					 | 
					 | 
					 | 
						sess     *session.Session | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// then keep a reference to it here.
 | 
					 | 
					 | 
					 | 
						s3Secret string | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						queuedPlaylistUpdates map[string]string | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						s3Bucket          string | 
					 | 
					 | 
					 | 
						s3Bucket          string | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						s3Region          string | 
					 | 
					 | 
					 | 
						s3Region          string | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						s3ServingEndpoint string | 
					 | 
					 | 
					 | 
						s3ServingEndpoint string | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						s3AccessKey       string | 
					 | 
					 | 
					 | 
						s3AccessKey       string | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						s3Secret          string | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						s3ACL             string | 
					 | 
					 | 
					 | 
						s3ACL             string | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						s3PathPrefix      string | 
					 | 
					 | 
					 | 
						s3PathPrefix      string | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						s3Endpoint string | 
					 | 
					 | 
					 | 
						s3Endpoint string | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						host       string | 
					 | 
					 | 
					 | 
						host       string | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						lock sync.Mutex | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						s3ForcePathStyle bool | 
					 | 
					 | 
					 | 
						s3ForcePathStyle bool | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -53,6 +57,7 @@ type S3Storage struct { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					func NewS3Storage() *S3Storage { | 
					 | 
					 | 
					 | 
					func NewS3Storage() *S3Storage { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						return &S3Storage{ | 
					 | 
					 | 
					 | 
						return &S3Storage{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							queuedPlaylistUpdates: make(map[string]string), | 
					 | 
					 | 
					 | 
							queuedPlaylistUpdates: make(map[string]string), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							lock:                  sync.Mutex{}, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -126,6 +131,8 @@ func (s *S3Storage) VariantPlaylistWritten(localFilePath string) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// We are uploading the variant playlist after uploading the segment
 | 
					 | 
					 | 
					 | 
						// We are uploading the variant playlist after uploading the segment
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// to make sure we're not referring to files in a playlist that don't
 | 
					 | 
					 | 
					 | 
						// to make sure we're not referring to files in a playlist that don't
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// yet exist.  See SegmentWritten.
 | 
					 | 
					 | 
					 | 
						// yet exist.  See SegmentWritten.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						s.lock.Lock() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						defer s.lock.Unlock() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if _, ok := s.queuedPlaylistUpdates[localFilePath]; ok { | 
					 | 
					 | 
					 | 
						if _, ok := s.queuedPlaylistUpdates[localFilePath]; ok { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if _, err := s.Save(localFilePath, 0); err != nil { | 
					 | 
					 | 
					 | 
							if _, err := s.Save(localFilePath, 0); err != nil { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								log.Errorln(err) | 
					 | 
					 | 
					 | 
								log.Errorln(err) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
  |