media/webrtc/signaling/src/common/YuvStamper.cpp

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #ifdef HAVE_NETINET_IN_H
     6 #include <netinet/in.h>
     7 #elif defined XP_WIN
     8 #include <winsock2.h>
     9 #endif
    10 #include <string.h>
    12 #include "nspr.h"
    13 #include "YuvStamper.h"
    15 typedef uint32_t UINT4; //Needed for r_crc32() call
    16 extern "C" {
    17 #include "r_crc32.h"
    18 }
    20 namespace mozilla {
    22 #define ON_5 0x20
    23 #define ON_4 0x10
    24 #define ON_3 0x08
    25 #define ON_2 0x04
    26 #define ON_1 0x02
    27 #define ON_0 0x01
    29 /*
    30   0, 0, 1, 1, 0, 0,
    31   0, 1, 0, 0, 1, 0,
    32   1, 0, 0, 0, 0, 1,
    33   1, 0, 0, 0, 0, 1,
    34   1, 0, 0, 0, 0, 1,
    35   0, 1, 0, 0, 1, 0,
    36   0, 0, 1, 1, 0, 0
    37 */
    38 static unsigned char DIGIT_0 [] =
    39   { ON_3 | ON_2,
    40     ON_4 | ON_1,
    41     ON_5 | ON_0,
    42     ON_5 | ON_0,
    43     ON_5 | ON_0,
    44     ON_4 | ON_1,
    45     ON_3 | ON_2
    46   };
    48 /*
    49   0, 0, 0, 1, 0, 0,
    50   0, 0, 0, 1, 0, 0,
    51   0, 0, 0, 1, 0, 0,
    52   0, 0, 0, 1, 0, 0,
    53   0, 0, 0, 1, 0, 0,
    54   0, 0, 0, 1, 0, 0,
    55   0, 0, 0, 1, 0, 0,
    56 */
    57 static unsigned char DIGIT_1 [] =
    58   { ON_2,
    59     ON_2,
    60     ON_2,
    61     ON_2,
    62     ON_2,
    63     ON_2,
    64     ON_2
    65   };
    67 /*
    68   1, 1, 1, 1, 1, 0,
    69   0, 0, 0, 0, 0, 1,
    70   0, 0, 0, 0, 0, 1,
    71   0, 1, 1, 1, 1, 0,
    72   1, 0, 0, 0, 0, 0,
    73   1, 0, 0, 0, 0, 0,
    74   0, 1, 1, 1, 1, 1,
    75 */
    76 static unsigned char DIGIT_2 [] =
    77   { ON_5 | ON_4 | ON_3 | ON_2 | ON_1,
    78     ON_0,
    79     ON_0,
    80     ON_4 | ON_3 | ON_2 | ON_1,
    81     ON_5,
    82     ON_5,
    83     ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
    84   };
    86 /*
    87   1, 1, 1, 1, 1, 0,
    88   0, 0, 0, 0, 0, 1,
    89   0, 0, 0, 0, 0, 1,
    90   0, 1, 1, 1, 1, 1,
    91   0, 0, 0, 0, 0, 1,
    92   0, 0, 0, 0, 0, 1,
    93   1, 1, 1, 1, 1, 0,
    94 */
    95 static unsigned char DIGIT_3 [] =
    96   { ON_5 | ON_4 | ON_3 | ON_2 | ON_1,
    97     ON_0,
    98     ON_0,
    99     ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
   100     ON_0,
   101     ON_0,
   102     ON_5 | ON_4 | ON_3 | ON_2 | ON_1,
   103   };
   105 /*
   106   0, 1, 0, 0, 0, 1,
   107   0, 1, 0, 0, 0, 1,
   108   0, 1, 0, 0, 0, 1,
   109   0, 1, 1, 1, 1, 1,
   110   0, 0, 0, 0, 0, 1,
   111   0, 0, 0, 0, 0, 1,
   112   0, 0, 0, 0, 0, 1
   113 */
   114 static unsigned char DIGIT_4 [] =
   115   { ON_4 | ON_0,
   116     ON_4 | ON_0,
   117     ON_4 | ON_0,
   118     ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
   119     ON_0,
   120     ON_0,
   121     ON_0,
   122   };
   124 /*
   125   0, 1, 1, 1, 1, 1,
   126   1, 0, 0, 0, 0, 0,
   127   1, 0, 0, 0, 0, 0,
   128   0, 1, 1, 1, 1, 0,
   129   0, 0, 0, 0, 0, 1,
   130   0, 0, 0, 0, 0, 1,
   131   1, 1, 1, 1, 1, 0,
   132 */
   133 static unsigned char DIGIT_5 [] =
   134   { ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
   135     ON_5,
   136     ON_5,
   137     ON_4 | ON_3 | ON_2 | ON_1,
   138     ON_0,
   139     ON_0,
   140     ON_5 | ON_4 | ON_3 | ON_2 | ON_1,
   141   };
   143 /*
   144   0, 1, 1, 1, 1, 1,
   145   1, 0, 0, 0, 0, 0,
   146   1, 0, 0, 0, 0, 0,
   147   1, 1, 1, 1, 1, 0,
   148   1, 0, 0, 0, 0, 1,
   149   1, 0, 0, 0, 0, 1,
   150   0, 1, 1, 1, 1, 0,
   151 */
   152 static unsigned char DIGIT_6 [] =
   153   { ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
   154     ON_5,
   155     ON_5,
   156     ON_4 | ON_3 | ON_2 | ON_1,
   157     ON_5 | ON_0,
   158     ON_5 | ON_0,
   159     ON_4 | ON_3 | ON_2 | ON_1,
   160   };
   162 /*
   163   1, 1, 1, 1, 1, 1,
   164   0, 0, 0, 0, 0, 1,
   165   0, 0, 0, 0, 1, 0,
   166   0, 0, 0, 1, 0, 0,
   167   0, 0, 1, 0, 0, 0,
   168   0, 1, 0, 0, 0, 0,
   169   1, 0, 0, 0, 0, 0
   170 */
   171 static unsigned char DIGIT_7 [] =
   172   { ON_5 | ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
   173     ON_0,
   174     ON_1,
   175     ON_2,
   176     ON_3,
   177     ON_4,
   178     ON_5
   179   };
   181 /*
   182   0, 1, 1, 1, 1, 1,
   183   1, 0, 0, 0, 0, 1,
   184   1, 0, 0, 0, 0, 1,
   185   0, 1, 1, 1, 1, 0,
   186   1, 0, 0, 0, 0, 1,
   187   1, 0, 0, 0, 0, 1,
   188   0, 1, 1, 1, 1, 0
   189 */
   190 static unsigned char DIGIT_8 [] =
   191   { ON_4 | ON_3 | ON_2 | ON_1,
   192     ON_5 | ON_0,
   193     ON_5 | ON_0,
   194     ON_4 | ON_3 | ON_2 | ON_1,
   195     ON_5 | ON_0,
   196     ON_5 | ON_0,
   197     ON_4 | ON_3 | ON_2 | ON_1,
   198   };
   200 /*
   201   0, 1, 1, 1, 1, 1,
   202   1, 0, 0, 0, 0, 1,
   203   1, 0, 0, 0, 0, 1,
   204   0, 1, 1, 1, 1, 1,
   205   0, 0, 0, 0, 0, 1,
   206   0, 0, 0, 0, 0, 1,
   207   0, 1, 1, 1, 1, 0
   208 */
   209 static unsigned char DIGIT_9 [] =
   210   { ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
   211     ON_5 | ON_0,
   212     ON_5 | ON_0,
   213     ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
   214     ON_0,
   215     ON_0,
   216     ON_4 | ON_3 | ON_2 | ON_1,
   217   };
   219 static unsigned char *DIGITS[] = {
   220     DIGIT_0,
   221     DIGIT_1,
   222     DIGIT_2,
   223     DIGIT_3,
   224     DIGIT_4,
   225     DIGIT_5,
   226     DIGIT_6,
   227     DIGIT_7,
   228     DIGIT_8,
   229     DIGIT_9
   230 };
   232   YuvStamper::YuvStamper(unsigned char* pYData,
   233 			 uint32_t width,
   234 			 uint32_t height,
   235 			 uint32_t stride,
   236 			 uint32_t x,
   237 			 uint32_t y,
   238 			 unsigned char symbol_width,
   239 			 unsigned char symbol_height):
   240     pYData(pYData), mStride(stride),
   241     mWidth(width), mHeight(height),
   242     mSymbolWidth(symbol_width), mSymbolHeight(symbol_height),
   243     mCursor(x, y) {}
   245   bool YuvStamper::Encode(uint32_t width, uint32_t height, uint32_t stride,
   246 			  unsigned char* pYData, unsigned char* pMsg, size_t msg_len,
   247 			  uint32_t x, uint32_t y)
   248   {
   249     YuvStamper stamper(pYData, width, height, stride,
   250 		       x, y, sBitSize, sBitSize);
   252     // Reserve space for a checksum.
   253     if (stamper.Capacity() < 8 * (msg_len + sizeof(uint32_t)))
   254     {
   255       return false;
   256     }
   258     bool ok = false;
   259     uint32_t crc;
   260     unsigned char* pCrc = reinterpret_cast<unsigned char*>(&crc);
   261     r_crc32(reinterpret_cast<char*>(pMsg), (int)msg_len, &crc);
   262     crc = htonl(crc);
   264     while (msg_len-- > 0) {
   265       if (!stamper.Write8(*pMsg++)) {
   266 	return false;
   267       }
   268     }
   270     // Add checksum after the message.
   271     ok = stamper.Write8(*pCrc++) &&
   272          stamper.Write8(*pCrc++) &&
   273          stamper.Write8(*pCrc++) &&
   274          stamper.Write8(*pCrc++);
   276     return ok;
   277   }
   279   bool YuvStamper::Decode(uint32_t width, uint32_t height, uint32_t stride,
   280 			  unsigned char* pYData, unsigned char* pMsg, size_t msg_len,
   281 			  uint32_t x, uint32_t y)
   282   {
   283     YuvStamper stamper(pYData, width, height, stride,
   284 		       x, y, sBitSize, sBitSize);
   286     unsigned char* ptr = pMsg;
   287     size_t len = msg_len;
   288     uint32_t crc, msg_crc;
   289     unsigned char* pCrc = reinterpret_cast<unsigned char*>(&crc);
   291     // Account for space reserved for the checksum
   292     if (stamper.Capacity() < 8 * (len + sizeof(uint32_t))) {
   293       return false;
   294     }
   296     while (len-- > 0) {
   297       if(!stamper.Read8(*ptr++)) {
   298 	return false;
   299       }
   300     }
   302     if (!(stamper.Read8(*pCrc++) &&
   303           stamper.Read8(*pCrc++) &&
   304           stamper.Read8(*pCrc++) &&
   305           stamper.Read8(*pCrc++))) {
   306       return false;
   307     }
   309     r_crc32(reinterpret_cast<char*>(pMsg), (int)msg_len, &msg_crc);
   310     return crc == htonl(msg_crc);
   311   }
   313   inline uint32_t YuvStamper::Capacity()
   314   {
   315     // Enforce at least a symbol width and height offset from outer edges.
   316     if (mCursor.y + mSymbolHeight > mHeight) {
   317       return 0;
   318     }
   320     if (mCursor.x + mSymbolWidth > mWidth && !AdvanceCursor()) {
   321       return 0;
   322     }
   324     // Normalize frame integral to mSymbolWidth x mSymbolHeight
   325     uint32_t width = mWidth / mSymbolWidth;
   326     uint32_t height = mHeight / mSymbolHeight;
   327     uint32_t x = mCursor.x / mSymbolWidth;
   328     uint32_t y = mCursor.y / mSymbolHeight;
   330     return (width * height - width * y)- x;
   331   }
   333   bool YuvStamper::Write8(unsigned char value)
   334   {
   335     // Encode MSB to LSB.
   336     unsigned char mask = 0x80;
   337     while (mask) {
   338       if (!WriteBit(!!(value & mask))) {
   339 	return false;
   340       }
   341       mask >>= 1;
   342     }
   343     return true;
   344   }
   346   bool YuvStamper::WriteBit(bool one)
   347   {
   348     // A bit is mapped to a mSymbolWidth x mSymbolHeight square of luma data points.
   349     // Don't use ternary op.: https://bugzilla.mozilla.org/show_bug.cgi?id=1001708
   350     unsigned char value;
   351     if (one)
   352       value = sYOn;
   353     else
   354       value = sYOff;
   356     for (uint32_t y = 0; y < mSymbolHeight; y++) {
   357       for (uint32_t x = 0; x < mSymbolWidth; x++) {
   358 	*(pYData + (mCursor.x + x) + ((mCursor.y + y) * mStride)) = value;
   359       }
   360     }
   362     return AdvanceCursor();
   363   }
   365   bool YuvStamper::AdvanceCursor()
   366   {
   367     mCursor.x += mSymbolWidth;
   368     if (mCursor.x + mSymbolWidth > mWidth) {
   369       // move to the start of the next row if possible.
   370       mCursor.y += mSymbolHeight;
   371       if (mCursor.y + mSymbolHeight > mHeight) {
   372 	// end of frame, do not advance
   373 	mCursor.y -= mSymbolHeight;
   374 	mCursor.x -= mSymbolWidth;
   375 	return false;
   376       } else {
   377 	mCursor.x = 0;
   378       }
   379     }
   381     return true;
   382   }
   384   bool YuvStamper::Read8(unsigned char &value)
   385   {
   386     unsigned char octet = 0;
   387     unsigned char bit = 0;
   389     for (int i = 8; i > 0; --i) {
   390       if (!ReadBit(bit)) {
   391 	return false;
   392       }
   393       octet <<= 1;
   394       octet |= bit;
   395     }
   397     value = octet;
   398     return true;
   399   }
   401   bool YuvStamper::ReadBit(unsigned char &bit)
   402   {
   403     uint32_t sum = 0;
   404     for (uint32_t y = 0; y < mSymbolHeight; y++) {
   405       for (uint32_t x = 0; x < mSymbolWidth; x++) {
   406 	sum += *(pYData + mStride * (mCursor.y + y) + mCursor.x + x);
   407       }
   408     }
   410     // apply threshold to collected bit square
   411     bit = (sum > (sBitThreshold * mSymbolWidth * mSymbolHeight)) ? 1 : 0;
   412     return AdvanceCursor();
   413   }
   415   bool YuvStamper::WriteDigits(uint32_t value)
   416   {
   417     char buf[20];
   418     PR_snprintf(buf, sizeof(buf), "%.5u", value);
   419     size_t size = strlen(buf);
   421     if (Capacity() < size) {
   422       return false;
   423     }
   425     for (size_t i=0; i < size; ++i) {
   426       if (!WriteDigit(buf[i] - '0'))
   427 	return false;
   428       if (!AdvanceCursor()) {
   429 	return false;
   430       }
   431     }
   433     return true;
   434   }
   436   bool YuvStamper::WriteDigit(unsigned char digit) {
   437     if (digit > sizeof(DIGITS)/sizeof(DIGITS[0]))
   438       return false;
   440     unsigned char *dig = DIGITS[digit];
   441     for (uint32_t row = 0; row < sDigitHeight; ++row) {
   442       unsigned char mask = 0x01 << (sDigitWidth - 1);
   443       for (uint32_t col = 0; col < sDigitWidth; ++col, mask >>= 1) {
   444 	if (dig[row] & mask) {
   445 	  for (uint32_t xx=0; xx < sPixelSize; ++xx) {
   446 	    for (uint32_t yy=0; yy < sPixelSize; ++yy) {
   447 	      WritePixel(pYData,
   448 			 mCursor.x + (col * sPixelSize) + xx,
   449 			 mCursor.y + (row * sPixelSize) + yy);
   450 	    }
   451 	  }
   452 	}
   453       }
   454     }
   456     return true;
   457   }
   459   void YuvStamper::WritePixel(unsigned char *data, uint32_t x, uint32_t y) {
   460     unsigned char *ptr = &data[y * mStride + x];
   461     // Don't use ternary op.: https://bugzilla.mozilla.org/show_bug.cgi?id=1001708
   462     if (*ptr > sLumaThreshold)
   463       *ptr = sLumaMin;
   464     else
   465       *ptr = sLumaMax;
   466    }
   468 }  // Namespace mozilla.

mercurial