Update content of files

This commit is contained in:
GitHub Action 2022-03-03 09:03:42 +00:00
parent c1839e3862
commit 0538fdf22b
7 changed files with 37 additions and 38 deletions

View file

@ -46,7 +46,7 @@
Technically, they are represented by <a href="/constructor/channel">channel</a> constructors. </p> Technically, they are represented by <a href="/constructor/channel">channel</a> constructors. </p>
<p><a href="https://telegram.org/tour/groups">Supergroups</a> are a powerful tool for building communities and can support up to 200,000 members each.<br> <p><a href="https://telegram.org/tour/groups">Supergroups</a> are a powerful tool for building communities and can support up to 200,000 members each.<br>
Technically, supergroups are actually channels: they are represented by <a href="/constructor/channel">channel</a> constructors, with the <code>megagroup</code> flag set to true. </p> Technically, supergroups are actually channels: they are represented by <a href="/constructor/channel">channel</a> constructors, with the <code>megagroup</code> flag set to true. </p>
<p>Gigagroups are something inbetween a channel and a supergroup.<br> <p>Gigagroups are something between a channel and a supergroup.<br>
An admin, <a href="/api/config#channel-suggestions">when prompted by the API using suggestions »</a>, can convert a megagroup into a gigagroup using <a href="/method/channels.convertToGigagroup">channels.convertToGigagroup</a> (one way only).<br> An admin, <a href="/api/config#channel-suggestions">when prompted by the API using suggestions »</a>, can convert a megagroup into a gigagroup using <a href="/method/channels.convertToGigagroup">channels.convertToGigagroup</a> (one way only).<br>
After that, only admins will be able to write in the group (like when <a href="#rights"><code>send_messages</code> rights are disabled for all group participants by default</a>), but the participant limit is removed and the group can become much bigger than a supergroup (e.g. &gt;200,000 currently).<br> After that, only admins will be able to write in the group (like when <a href="#rights"><code>send_messages</code> rights are disabled for all group participants by default</a>), but the participant limit is removed and the group can become much bigger than a supergroup (e.g. &gt;200,000 currently).<br>
Also, one can't invite people into gigagroups and participants of voice chats in gigagroups are muted by default. </p> Also, one can't invite people into gigagroups and participants of voice chats in gigagroups are muted by default. </p>

View file

@ -46,7 +46,7 @@
<h4><a class="anchor" href="#error-type" id="error-type" name="error-type"><i class="anchor-icon"></i></a>Error Type</h4> <h4><a class="anchor" href="#error-type" id="error-type" name="error-type"><i class="anchor-icon"></i></a>Error Type</h4>
<p>A string literal in the form of <code>/[A-Z_0-9]+/</code>, which summarizes the problem. For example, <code>AUTH_KEY_UNREGISTERED</code>. This is an optional parameter.</p> <p>A string literal in the form of <code>/[A-Z_0-9]+/</code>, which summarizes the problem. For example, <code>AUTH_KEY_UNREGISTERED</code>. This is an optional parameter.</p>
<h4><a class="anchor" href="#error-database" id="error-database" name="error-database"><i class="anchor-icon"></i></a>Error Database</h4> <h4><a class="anchor" href="#error-database" id="error-database" name="error-database"><i class="anchor-icon"></i></a>Error Database</h4>
<p>A full machine-readable JSON list of RPC errors that can be returned by all methods in the API can be found <a href="/file/464001158/122a8/nbJqCk-fuss.77184.json/42ea6a04359d8b7c39">here »</a>, what follows is a description of its fields: </p> <p>A full machine-readable JSON list of RPC errors that can be returned by all methods in the API can be found <a href="/file/464001971/11361/nCsgOjxdfxA.77184.json/a27921641b664931c6">here »</a>, what follows is a description of its fields: </p>
<ul> <ul>
<li><code>errors</code> - All error messages and codes for each method (object).<ul> <li><code>errors</code> - All error messages and codes for each method (object).<ul>
<li>Keys: Error codes as strings (numeric strings)</li> <li>Keys: Error codes as strings (numeric strings)</li>
@ -140,7 +140,7 @@
<li>USER_DEACTIVATED: The user has been deleted/deactivated</li> <li>USER_DEACTIVATED: The user has been deleted/deactivated</li>
<li>SESSION_REVOKED: The authorization has been invalidated, because of the user terminating all sessions</li> <li>SESSION_REVOKED: The authorization has been invalidated, because of the user terminating all sessions</li>
<li>SESSION_EXPIRED: The authorization has expired</li> <li>SESSION_EXPIRED: The authorization has expired</li>
<li>AUTH_KEY_PERM_EMPTY: The method is unavailble for temporary authorization key, not bound to permanent</li> <li>AUTH_KEY_PERM_EMPTY: The method is unavailable for temporary authorization key, not bound to permanent</li>
</ul> </ul>
<h3><a class="anchor" href="#403-forbidden" id="403-forbidden" name="403-forbidden"><i class="anchor-icon"></i></a>403 FORBIDDEN</h3> <h3><a class="anchor" href="#403-forbidden" id="403-forbidden" name="403-forbidden"><i class="anchor-icon"></i></a>403 FORBIDDEN</h3>
<p>Privacy violation. For example, an attempt to write a message to someone who has blacklisted the current user.</p> <p>Privacy violation. For example, an attempt to write a message to someone who has blacklisted the current user.</p>

View file

@ -74,7 +74,7 @@
<h4><a class="anchor" href="#data-compression-when-making-a-request" id="data-compression-when-making-a-request" name="data-compression-when-making-a-request"><i class="anchor-icon"></i></a>Data Compression when Making a Request</h4> <h4><a class="anchor" href="#data-compression-when-making-a-request" id="data-compression-when-making-a-request" name="data-compression-when-making-a-request"><i class="anchor-icon"></i></a>Data Compression when Making a Request</h4>
<p>Before transmitting a query, the string containing the entire body of the serialized high-level query (starting with the method number) must be compressed using gzip. If the resulting string is smaller than the original, it makes sense to transmit the <a href="/mtproto/service_messages#pakovannyy-obekt">gzip_packed</a> constructor.</p> <p>Before transmitting a query, the string containing the entire body of the serialized high-level query (starting with the method number) must be compressed using gzip. If the resulting string is smaller than the original, it makes sense to transmit the <a href="/mtproto/service_messages#pakovannyy-obekt">gzip_packed</a> constructor.</p>
<p>There is no point in doing the above when transmitting binary multimedia data (photos, videos) or small messages (up to 255 bytes).</p> <p>There is no point in doing the above when transmitting binary multimedia data (photos, videos) or small messages (up to 255 bytes).</p>
<h4><a class="anchor" href="#uncompressing-data" id="uncompressing-data" name="uncompressing-data"><i class="anchor-icon"></i></a>Uncompressing Data</h4> <h4><a class="anchor" href="#decompressing-data" id="decompressing-data" name="decompressing-data"><i class="anchor-icon"></i></a>Decompressing Data</h4>
<p>By default, the server compresses the response to any request as well as <a href="/api/updates">updates</a>, in accordance with the rules stated above. If the <a href="/mtproto/service_messages#packed-object">gzip_packed</a> constructor is received as a response in rpc_result, then the string that follows must be extracted and uncompressed. Processing then continues on the resulting new string.</p></div> <p>By default, the server compresses the response to any request as well as <a href="/api/updates">updates</a>, in accordance with the rules stated above. If the <a href="/mtproto/service_messages#packed-object">gzip_packed</a> constructor is received as a response in rpc_result, then the string that follows must be extracted and uncompressed. Processing then continues on the resulting new string.</p></div>
</div> </div>

View file

@ -43,7 +43,7 @@
<p>Lots of Telegram API methods provide access to potentially large lists of objects, which requires pagination.</p> <p>Lots of Telegram API methods provide access to potentially large lists of objects, which requires pagination.</p>
<p>In order to fetch only relevant subset of results for each request there is a number of available input parameters. Here is a list in order how they are applied in API.</p> <p>In order to fetch only relevant subset of results for each request there is a number of available input parameters. Here is a list in order how they are applied in API.</p>
<p>Typically, results are returned in antichronological order with descending object ID values.</p> <p>Typically, results are returned in reverse chronological order with descending object ID values.</p>
<h3><a class="anchor" href="#limit-parameter" id="limit-parameter" name="limit-parameter"><i class="anchor-icon"></i></a><code>limit</code> parameter</h3> <h3><a class="anchor" href="#limit-parameter" id="limit-parameter" name="limit-parameter"><i class="anchor-icon"></i></a><code>limit</code> parameter</h3>
<p>A limit on the number of objects to be returned, typically between 1 and 100. When 0 is provided the limit will often default to an intermediate value like ~20.</p> <p>A limit on the number of objects to be returned, typically between 1 and 100. When 0 is provided the limit will often default to an intermediate value like ~20.</p>
<h3><a class="anchor" href="#offset-based-pagination" id="offset-based-pagination" name="offset-based-pagination"><i class="anchor-icon"></i></a><code>offset</code>-based pagination</h3> <h3><a class="anchor" href="#offset-based-pagination" id="offset-based-pagination" name="offset-based-pagination"><i class="anchor-icon"></i></a><code>offset</code>-based pagination</h3>

View file

@ -46,7 +46,7 @@
<p>Update events are sent to an authorized user into the last active connection (except for connections needed for downloading / uploading files).</p> <p>Update events are sent to an authorized user into the last active connection (except for connections needed for downloading / uploading files).</p>
<p>So to start receiving updates the client needs to init connection and call API method, e.g. to <a href="#fetching-state">fetch current state</a>.</p> <p>So to start receiving updates the client needs to init connection and call API method, e.g. to <a href="#fetching-state">fetch current state</a>.</p>
<h3><a class="anchor" href="#event-sequences" id="event-sequences" name="event-sequences"><i class="anchor-icon"></i></a>Event sequences</h3> <h3><a class="anchor" href="#event-sequences" id="event-sequences" name="event-sequences"><i class="anchor-icon"></i></a>Event sequences</h3>
<p>All events are received from the socket as a sequence of TL-serialized <a href="/type/Updates">Updates</a> objects, which might be optionally gzip-compressed in the same way as <a href="/api/invoking#uncompressing-data">responses to queries</a>.</p> <p>All events are received from the socket as a sequence of TL-serialized <a href="/type/Updates">Updates</a> objects, which might be optionally gzip-compressed in the same way as <a href="/api/invoking#decompressing-data">responses to queries</a>.</p>
<p>Each <a href="/type/Updates">Updates</a> object may contain single or multiple <a href="/type/Update">Update</a> objects, representing different events happening.</p> <p>Each <a href="/type/Updates">Updates</a> object may contain single or multiple <a href="/type/Update">Update</a> objects, representing different events happening.</p>
<p>In order to apply all updates in precise order and to guarantee that no update is missed or applied twice there is <code>seq</code> attribute in <a href="/type/Updates">Updates</a> constructors, and <code>pts</code> (with <code>pts_count</code>) or <code>qts</code> attributes in <a href="/type/Update">Update</a> constructors. The client must use those attributes values in combination with locally stored state to correctly apply incoming updates.</p> <p>In order to apply all updates in precise order and to guarantee that no update is missed or applied twice there is <code>seq</code> attribute in <a href="/type/Updates">Updates</a> constructors, and <code>pts</code> (with <code>pts_count</code>) or <code>qts</code> attributes in <a href="/type/Update">Update</a> constructors. The client must use those attributes values in combination with locally stored state to correctly apply incoming updates.</p>
<p>When a gap in updates sequence occurs, it must be filled via calling one of the API methods. <a href="#recovering-gaps">More below »</a></p> <p>When a gap in updates sequence occurs, it must be filled via calling one of the API methods. <a href="#recovering-gaps">More below »</a></p>

View file

@ -39,82 +39,82 @@
<div class="dev_page_bread_crumbs"></div> <div class="dev_page_bread_crumbs"></div>
<h1 id="dev_page_title">Encrypted CDNs for Speed and Security</h1> <h1 id="dev_page_title">Encrypted CDNs for Speed and Security</h1>
<div id="dev_page_content"><p>Following the launch of version 4.2 of the official apps, Telegram client apps may be required to download popular files that were published in public channels with more than <strong>100,000</strong> members from secondary <a href="https://en.wikipedia.org/wiki/Content_delivery_network">Content Delivery Network</a> data centers. These CDN DCs are located in regions with significant Telegram traffic where we wouldn&#39;t want to place Telegram servers for various reasons.</p> <div id="dev_page_content"><p>Following the launch of version 4.2 of the official apps, Telegram client apps may be required to download popular files that were published in public channels with more than <strong>100,000</strong> members from secondary <a href="https://en.wikipedia.org/wiki/Content_delivery_network">Content Delivery Network</a> data centers. These CDN DCs are located in regions with significant Telegram traffic where we wouldn't want to place Telegram servers for various reasons.</p>
<p>The CDN DCs are not a part of the Telegram cloud and should be considered enemy territory. For this reason, each file that is to be sent to these CDN DCs is encrypted with a unique key using AES-256-CTR encryption. The CDN <strong>can&#39;t access the data</strong> it stores because these keys are only accessible to the main MTProto server and to the authorized client.</p> <p>The CDN DCs are not a part of the Telegram cloud and should be considered enemy territory. For this reason, each file that is to be sent to these CDN DCs is encrypted with a unique key using AES-256-CTR encryption. The CDN <strong>can't access the data</strong> it stores because these keys are only accessible to the main MTProto server and to the authorized client.</p>
<blockquote> <blockquote>
<p><strong>See also:</strong> <a href="/techfaq#encrypted-cdns">More about CDNs and governments in the Advanced FAQ</a></p> <p><strong>See also:</strong> <a href="/techfaq#encrypted-cdns">More about CDNs and governments in the Advanced FAQ</a></p>
</blockquote> </blockquote>
<h3><a class="anchor" name="how-this-works" href="#how-this-works"><i class="anchor-icon"></i></a>How this works</h3> <h3><a class="anchor" href="#how-this-works" id="how-this-works" name="how-this-works"><i class="anchor-icon"></i></a>How this works</h3>
<p>When a file from a public channel with <strong>~100,000</strong> members becomes popular in a particular region, the Telegram server may encrypt this file with a unique AES-256-CTR key and send it to a relevant CDN DC for storage.</p> <p>When a file from a public channel with <strong>~100,000</strong> members becomes popular in a particular region, the Telegram server may encrypt this file with a unique AES-256-CTR key and send it to a relevant CDN DC for storage.</p>
<p>When a file is stored in a CDN DC close to the end user, the download speed will be much higher because the data needs to travel smaller distances and will likely avoid many bottlenecks that exist between regions.</p> <p>When a file is stored in a CDN DC close to the end user, the download speed will be much higher because the data needs to travel smaller distances and will likely avoid many bottlenecks that exist between regions.</p>
<p>This is secure because CDN DCs are treated the same way as internet providers / random third parties:</p> <p>This is secure because CDN DCs are treated the same way as internet providers / random third parties:</p>
<ul> <ul>
<li>CDN DCs dont have the keys to decrypt files that are stored there, so they cant access the data even if a DC becomes compromised.</li> <li>CDN DCs don't have the keys to decrypt files that are stored there, so they can't access the data even if a DC becomes compromised.</li>
<li>Encrypted files fragments are protected from tampering by their SHA-256 hash which is checked on the client upon receipt.</li> <li>Encrypted files fragments are protected from tampering by their SHA-256 hash which is checked on the client upon receipt.</li>
<li>No private data is stored in or passed to the CDN DCs.</li> <li>No private data is stored in or passed to the CDN DCs.</li>
<li>The server only allows media from public channels with more than <strong>100,000</strong> subscribers to be cached in CDN DCs (this includes media forwarded from those channels and viral media that originated from other large public channels).</li> <li>The server only allows media from public channels with more than <strong>100,000</strong> subscribers to be cached in CDN DCs (this includes media forwarded from those channels and viral media that originated from other large public channels).</li>
</ul> </ul>
<div> <div>
<a href="/file/811140934/1815/aSQ-nSUHJzc.45662/40c2955965574cef80" target="_blank"><img src="/file/811140934/1815/aSQ-nSUHJzc.45662/40c2955965574cef80" title="CDNs explained" class="dev_page_image" /></a> <a href="/file/811140934/1815/aSQ-nSUHJzc.45662/40c2955965574cef80" target="_blank"><img src="/file/811140934/1815/aSQ-nSUHJzc.45662/40c2955965574cef80" title="CDNs explained" class="dev_page_image"></a>
</div> </div>
<p>CDNs are very limited when it comes to communication: the master data center only uploads encrypted files for storage and will accept no data from the CDN. The client apps only download encrypted files and accept no other updates. The client apps obtain the keys necessary to decrypt the file from the main Telegram server and verify the integrity of the file by its hash, which means that the CDN may only supply the correct file  anything different will be immediately discarded by the client.</p>
<p>CDNs are very limited when it comes to communication: the master data center only uploads encrypted files for storage and will accept no data from the CDN. The client apps only download encrypted files and accept no other updates. The client apps obtain the keys necessary to decrypt the file from the main Telegram server and verify the integrity of the file by its hash, which means that the CDN may only supply the correct file anything different will be immediately discarded by the client.</p>
<p>CDN DCs do not store files on hard disks only in memory. When a CDN server runs out of memory, a simple LRU algorithm is used to replace the least popular files with new ones.</p> <p>CDN DCs do not store files on hard disks only in memory. When a CDN server runs out of memory, a simple LRU algorithm is used to replace the least popular files with new ones.</p>
<h3><a class="anchor" name="how-cdn-dcs-are-different-from-the-master-dcs" href="#how-cdn-dcs-are-different-from-the-master-dcs"><i class="anchor-icon"></i></a>How CDN DCs are different from the master DCs</h3> <h3><a class="anchor" href="#how-cdn-dcs-are-different-from-the-master-dcs" id="how-cdn-dcs-are-different-from-the-master-dcs" name="how-cdn-dcs-are-different-from-the-master-dcs"><i class="anchor-icon"></i></a>How CDN DCs are different from the master DCs</h3>
<ul> <ul>
<li><strong>CDNs may not be trusted.</strong></li> <li><strong>CDNs may not be trusted.</strong></li>
<li>Client developers can use <a href="/method/help.getCdnConfig">help.getCdnConfig</a> to obtain a list of public RSA keys for CDN DCs, which are different from public RSA keys of the master DCs.</li> <li>Client developers can use <a href="/method/help.getCdnConfig">help.getCdnConfig</a> to obtain a list of public RSA keys for CDN DCs, which are different from public RSA keys of the master DCs.</li>
<li>CDNs support only the following methods: <a href="/method/upload.getCdnFile">upload.getCdnFile</a>, <a href="/method/initConnection">initConnection</a>, <a href="/method/invokeWithLayer">invokeWithLayer</a>.</li> <li>CDNs support only the following methods: <a href="/method/upload.getCdnFile">upload.getCdnFile</a>, <a href="/method/initConnection">initConnection</a>, <a href="/method/invokeWithLayer">invokeWithLayer</a>.</li>
<li>When working with CDNs, client developers must remember that auth_key may be deleted at any given moment (resulting in a -404 error, in which case a new key must be generated).</li> <li>When working with CDNs, client developers must remember that auth_key may be deleted at any given moment (resulting in a -404 error, in which case a new key must be generated).</li>
<li>Client apps must not accept updates from CDN DCs (apps should only accept updates from their main connection to the master DC).</li> <li>Client apps must not accept updates from CDN DCs (apps should only accept updates from their main connection to the master DC).</li>
<li>Clients must not allow the CDN DCs to substitute replies to queries sent to other DCs.</li> <li>Clients must not allow the CDN DCs to substitute replies to queries sent to other DCs.</li>
<li>Clients must not send private user info that is passed in <a href="/method/initConnection">initConnection</a> to the CDNs.</li> <li>Clients must not send private user info that is passed in <a href="/method/initConnection">initConnection</a> to the CDNs.</li>
</ul> </ul>
<h3><a class="anchor" name="getting-files-from-a-cdn" href="#getting-files-from-a-cdn"><i class="anchor-icon"></i></a>Getting files from a CDN</h3> <h3><a class="anchor" href="#getting-files-from-a-cdn" id="getting-files-from-a-cdn" name="getting-files-from-a-cdn"><i class="anchor-icon"></i></a>Getting files from a CDN</h3>
<p>The API may return the <a href="/constructor/upload.fileCdnRedirect">upload.fileCdnRedirect</a> constructor after an <a href="/method/upload.getFile">upload.getFile</a> query. In this case, the client must request the required file from a CDN DC. The <em>dc_id</em> in the response is the id of the new CDN. The IP address for the connection will be available in <a href="/method/help.getConfig">help.getConfig</a>, same as with the master DCs. The corresponding <a href="/constructor/dcOption">dcOption</a> will have the flag <em>cdn:flags.3?true</em>.</p> <p>The API may return the <a href="/constructor/upload.fileCdnRedirect">upload.fileCdnRedirect</a> constructor after an <a href="/method/upload.getFile">upload.getFile</a> query. In this case, the client must request the required file from a CDN DC. The <em>dc_id</em> in the response is the id of the new CDN. The IP address for the connection will be available in <a href="/method/help.getConfig">help.getConfig</a>, same as with the master DCs. The corresponding <a href="/constructor/dcOption">dcOption</a> will have the flag <em>cdn:flags.3?true</em>.</p>
<p>Once a successful connection to the CDN-dc_id is established, the client must generate an auth_key (after confirming that the public RSA MTProto key of the CDN DC matches one from the list returned in <a href="/method/help.getCdnConfig">help.getCdnConfig</a>). Then the client must perform an <a href="/method/upload.getCdnFile">upload.getCdnFile</a> for each <em>offset</em>. For files of an unknown size it is necessary to repeat the query until an empty reply is returned.</p> <p>Once a successful connection to the CDN-dc_id is established, the client must generate an auth_key (after confirming that the public RSA MTProto key of the CDN DC matches one from the list returned in <a href="/method/help.getCdnConfig">help.getCdnConfig</a>). Then the client must perform an <a href="/method/upload.getCdnFile">upload.getCdnFile</a> for each <em>offset</em>. For files of an unknown size it is necessary to repeat the query until an empty reply is returned.</p>
<p><a href="/method/upload.getCdnFile">upload.getCdnFile</a> may return the <a href="/constructor/upload.cdnFileReuploadNeeded">upload.cdnFileReuploadNeeded</a> constructor. In this case, the client needs to send an <a href="/method/upload.reuploadCdnFile">upload.reuploadCdnFile</a> request to the DC that got the original <a href="/method/upload.getFile">upload.getFile</a> request. Once <a href="/method/upload.reuploadCdnFile">upload.reuploadCdnFile</a> is successfull, the app needs to request the file from the CDN DC again.</p> <p><a href="/method/upload.getCdnFile">upload.getCdnFile</a> may return the <a href="/constructor/upload.cdnFileReuploadNeeded">upload.cdnFileReuploadNeeded</a> constructor. In this case, the client needs to send an <a href="/method/upload.reuploadCdnFile">upload.reuploadCdnFile</a> request to the DC that got the original <a href="/method/upload.getFile">upload.getFile</a> request. Once <a href="/method/upload.reuploadCdnFile">upload.reuploadCdnFile</a> is successful, the app needs to request the file from the CDN DC again.</p>
<p>The main DC for a file is the DC where its main copy is stored (not to be confused with the main DC of the user) either <em>userProfilePhoto.dc_id</em>, <em>chatPhoto.dc_id</em>, <em>photo.dc_id</em>, or <em>document.dc_id</em>.</p> <p>The main DC for a file is the DC where its main copy is stored (not to be confused with the main DC of the user) either <em>userProfilePhoto.dc_id</em>, <em>chatPhoto.dc_id</em>, <em>photo.dc_id</em>, or <em>document.dc_id</em>.</p>
<h3><a class="anchor" name="decrypting-files" href="#decrypting-files"><i class="anchor-icon"></i></a>Decrypting files</h3> <h3><a class="anchor" href="#decrypting-files" id="decrypting-files" name="decrypting-files"><i class="anchor-icon"></i></a>Decrypting files</h3>
<p>In <a href="/constructor/upload.fileCdnRedirect">upload.fileCdnRedirect</a>, the server sends a decryption key and IV for the file (the fields <code>encryption_key:bytes</code> and <code>encryption_iv:bytes</code> respectively).</p> <p>In <a href="/constructor/upload.fileCdnRedirect">upload.fileCdnRedirect</a>, the server sends a decryption key and IV for the file (the fields <code>encryption_key:bytes</code> and <code>encryption_iv:bytes</code> respectively).</p>
<p>Having received a portion of encrypted data from the CDN DC inside <a href="/constructor/upload.cdnFile">upload.cdnFile</a>, the client must decrypt this data using <code>AES-256-CTR</code>. For IV, it should use the value of <code>encryption_iv</code>, modified in the following manner: for each <code>offset</code> replace the last 4 bytes of the <code>encryption_iv</code> with <code>offset / 16</code> in big-endian. This allows to effectively decrypt a file and to use random access to a file&#39;s content (e.g., for streaming).</p> <p>Having received a portion of encrypted data from the CDN DC inside <a href="/constructor/upload.cdnFile">upload.cdnFile</a>, the client must decrypt this data using <code>AES-256-CTR</code>. For IV, it should use the value of <code>encryption_iv</code>, modified in the following manner: for each <code>offset</code> replace the last 4 bytes of the <code>encryption_iv</code> with <code>offset / 16</code> in big-endian. This allows to effectively decrypt a file and to use random access to a file's content (e.g., for streaming).</p>
<h3><a class="anchor" name="verifying-files" href="#verifying-files"><i class="anchor-icon"></i></a>Verifying files</h3> <h3><a class="anchor" href="#verifying-files" id="verifying-files" name="verifying-files"><i class="anchor-icon"></i></a>Verifying files</h3>
<p>In order to confirm that the CDN DC passed an untampered file, clients must verify hashes for each downloaded part. <a href="/constructor/upload.fileCdnRedirect">upload.fileCdnRedirect</a>, <a href="/method/upload.reuploadCdnFile">upload.reuploadCdnFile</a> and <a href="/method/upload.getCdnFileHashes">upload.getCdnFileHashes</a> contain <a href="/type/FileHash">FileHash</a> constructors. Each of these constructors contains the SHA-256 hash of a part of the file that starts with <code>offset</code> and takes <code>limit</code> bytes.</p> <p>In order to confirm that the CDN DC passed an untampered file, clients must verify hashes for each downloaded part. <a href="/constructor/upload.fileCdnRedirect">upload.fileCdnRedirect</a>, <a href="/method/upload.reuploadCdnFile">upload.reuploadCdnFile</a> and <a href="/method/upload.getCdnFileHashes">upload.getCdnFileHashes</a> contain <a href="/type/FileHash">FileHash</a> constructors. Each of these constructors contains the SHA-256 hash of a part of the file that starts with <code>offset</code> and takes <code>limit</code> bytes.</p>
<p>Before saving each portion of the data received from the CDN DC into the file, the client must confirm that its hash matches the hash that was received from the master DC. If missing a hash for any file part, client developers must use the <a href="/method/upload.getCdnFileHashes">upload.getCdnFileHashes</a> method to obtain the missing hash.</p> <p>Before saving each portion of the data received from the CDN DC into the file, the client must confirm that its hash matches the hash that was received from the master DC. If missing a hash for any file part, client developers must use the <a href="/method/upload.getCdnFileHashes">upload.getCdnFileHashes</a> method to obtain the missing hash.</p>
<h3><a class="anchor" name="schema" href="#schema"><i class="anchor-icon"></i></a>Schema</h3> <h3><a class="anchor" href="#schema" id="schema" name="schema"><i class="anchor-icon"></i></a>Schema</h3>
<pre><code>fileHash#6242c773 offset:int limit:int hash:bytes = FileHash; <pre><code><a href='/constructor/fileHash'>fileHash</a>#6242c773 offset:<a href='/type/int'>int</a> limit:<a href='/type/int'>int</a> hash:<a href='/type/bytes'>bytes</a> = <a href='/type/FileHash'>FileHash</a>;
upload.fileCdnRedirect#f18cda44 dc_id:int file_token:bytes encryption_key:bytes encryption_iv:bytes file_hashes:Vector&lt;FileHash&gt; = upload.File; <a href='/constructor/upload.fileCdnRedirect'>upload.fileCdnRedirect</a>#f18cda44 dc_id:<a href='/type/int'>int</a> file_token:<a href='/type/bytes'>bytes</a> encryption_key:<a href='/type/bytes'>bytes</a> encryption_iv:<a href='/type/bytes'>bytes</a> file_hashes:<a href='/type/Vector%20t'>Vector</a>&lt;<a href='/type/FileHash'>FileHash</a>&gt; = <a href='/type/upload.File'>upload.File</a>;
upload.cdnFileReuploadNeeded#eea8e46e request_token:bytes = upload.CdnFile; <a href='/constructor/upload.cdnFileReuploadNeeded'>upload.cdnFileReuploadNeeded</a>#eea8e46e request_token:<a href='/type/bytes'>bytes</a> = <a href='/type/upload.CdnFile'>upload.CdnFile</a>;
upload.cdnFile#a99fca4f bytes:bytes = upload.CdnFile; <a href='/constructor/upload.cdnFile'>upload.cdnFile</a>#a99fca4f bytes:<a href='/type/bytes'>bytes</a> = <a href='/type/upload.CdnFile'>upload.CdnFile</a>;
dcOption#18b7a10d flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true static:flags.4?true id:int ip_address:string port:int secret:flags.10?bytes = DcOption; <a href='/constructor/dcOption'>dcOption</a>#18b7a10d flags:<a href='/type/%23'>#</a> ipv6:flags.0?<a href='/constructor/true'>true</a> media_only:flags.1?<a href='/constructor/true'>true</a> tcpo_only:flags.2?<a href='/constructor/true'>true</a> cdn:flags.3?<a href='/constructor/true'>true</a> static:flags.4?<a href='/constructor/true'>true</a> id:<a href='/type/int'>int</a> ip_address:<a href='/type/string'>string</a> port:<a href='/type/int'>int</a> secret:flags.10?<a href='/type/bytes'>bytes</a> = <a href='/type/DcOption'>DcOption</a>;
cdnPublicKey#c982eaba dc_id:int public_key:string = CdnPublicKey; <a href='/constructor/cdnPublicKey'>cdnPublicKey</a>#c982eaba dc_id:<a href='/type/int'>int</a> public_key:<a href='/type/string'>string</a> = <a href='/type/CdnPublicKey'>CdnPublicKey</a>;
cdnConfig#5725e40a public_keys:Vector&lt;CdnPublicKey&gt; = CdnConfig; <a href='/constructor/cdnConfig'>cdnConfig</a>#5725e40a public_keys:<a href='/type/Vector%20t'>Vector</a>&lt;<a href='/type/CdnPublicKey'>CdnPublicKey</a>&gt; = <a href='/type/CdnConfig'>CdnConfig</a>;
---functions--- ---functions---
// CDN DC // CDN DC
upload.getCdnFile#2000bcc3 file_token:bytes offset:int limit:int = upload.CdnFile; <a href='/method/upload.getCdnFile'>upload.getCdnFile</a>#2000bcc3 file_token:<a href='/type/bytes'>bytes</a> offset:<a href='/type/int'>int</a> limit:<a href='/type/int'>int</a> = <a href='/type/upload.CdnFile'>upload.CdnFile</a>;
// Master DC // Master DC
upload.reuploadCdnFile#9b2754a8 file_token:bytes request_token:bytes = Vector&lt;FileHash&gt;; <a href='/method/upload.reuploadCdnFile'>upload.reuploadCdnFile</a>#9b2754a8 file_token:<a href='/type/bytes'>bytes</a> request_token:<a href='/type/bytes'>bytes</a> = <a href='/type/Vector%20t'>Vector</a>&lt;<a href='/type/FileHash'>FileHash</a>&gt;;
upload.getCdnFileHashes#4da54231 file_token:bytes offset:int = Vector&lt;FileHash&gt;; <a href='/method/upload.getCdnFileHashes'>upload.getCdnFileHashes</a>#4da54231 file_token:<a href='/type/bytes'>bytes</a> offset:<a href='/type/int'>int</a> = <a href='/type/Vector%20t'>Vector</a>&lt;<a href='/type/FileHash'>FileHash</a>&gt;;
help.getCdnConfig#52029342 = CdnConfig;</code></pre> <a href='/method/help.getCdnConfig'>help.getCdnConfig</a>#52029342 = <a href='/type/CdnConfig'>CdnConfig</a>;</code></pre>
<h3><a class="anchor" name="restrictions-on-upload-getfile-and-upload-getcdnfile-parameters" href="#restrictions-on-upload-getfile-and-upload-getcdnfile-parameters"><i class="anchor-icon"></i></a>Restrictions on upload.getFile and upload.getCdnFile parameters</h3> <h3><a class="anchor" href="#restrictions-on-uploadgetfile-and-uploadgetcdnfile-parameters" id="restrictions-on-uploadgetfile-and-uploadgetcdnfile-parameters" name="restrictions-on-uploadgetfile-and-uploadgetcdnfile-parameters"><i class="anchor-icon"></i></a>Restrictions on upload.getFile and upload.getCdnFile parameters</h3>
<ul> <ul>
<li><code>offset</code> must be divisible by 4096 bytes</li> <li><code>offset</code> must be divisible by 4096 bytes</li>
<li><code>limit</code> must be divisible by 4096 bytes</li> <li><code>limit</code> must be divisible by 4096 bytes</li>
<li>1048576 (1MB) must be divisible by <code>limit</code></li> <li>1048576 (1MB) must be divisible by <code>limit</code></li>
<li><code>offset / (1024 * 1024) == (offset + limit - 1) / (1024 * 1024)</code><br>(file parts that are being downloaded must always be inside the same megabyte-sized fragment)</li> <li><code>offset / (1024 * 1024) == (offset + limit - 1) / (1024 * 1024)</code>
(file parts that are being downloaded must always be inside the same megabyte-sized fragment)</li>
</ul> </ul>
<h3><a class="anchor" name="possible-errors-and-their-meanings" href="#possible-errors-and-their-meanings"><i class="anchor-icon"></i></a>Possible errors and their meanings</h3> <h3><a class="anchor" href="#possible-errors-and-their-meanings" id="possible-errors-and-their-meanings" name="possible-errors-and-their-meanings"><i class="anchor-icon"></i></a>Possible errors and their meanings</h3>
<table class="table"> <table class="table">
<tbody> <tbody>
<tr> <tr>
@ -133,8 +133,7 @@ help.getCdnConfig#52029342 = CdnConfig;</code></pre>
<td>The master DC did not accept the <code>request_token</code> from the CDN DC. Continue downloading the file from the master DC using upload.getFile.</td> <td>The master DC did not accept the <code>request_token</code> from the CDN DC. Continue downloading the file from the master DC using upload.getFile.</td>
</tr> </tr>
</tbody> </tbody>
</table> </table></div>
</div>
</div> </div>

View file

@ -39,7 +39,7 @@
<div class="dev_page_bread_crumbs"><ul class="breadcrumb clearfix"><li><a href="/api" >API</a></li><i class="icon icon-breadcrumb-divider"></i><li><a href="/methods" >All Methods</a></li><i class="icon icon-breadcrumb-divider"></i><li><a href="/method/help.getSupport" >help.getSupport</a></li></ul></div> <div class="dev_page_bread_crumbs"><ul class="breadcrumb clearfix"><li><a href="/api" >API</a></li><i class="icon icon-breadcrumb-divider"></i><li><a href="/methods" >All Methods</a></li><i class="icon icon-breadcrumb-divider"></i><li><a href="/method/help.getSupport" >help.getSupport</a></li></ul></div>
<h1 id="dev_page_title">help.getSupport</h1> <h1 id="dev_page_title">help.getSupport</h1>
<div id="dev_page_content"><p>Returns the support user for the 'ask a question' feature.</p> <div id="dev_page_content"><p>Returns the support user for the "ask a question" feature.</p>
<p><div class="clearfix"> <p><div class="clearfix">
<ul class="dev_layer_select slightly-pull-right nav nav-pills"> <ul class="dev_layer_select slightly-pull-right nav nav-pills">
<li class="dropdown"> <li class="dropdown">