示例#1
0
bool    Plugin::onLoad(LightBird::IApi *api)
{
    int         error;
    const char  *err_pos = NULL;

    this->api = api;
    try
    {
        ASSERT_INIT(gnutls_global_init(), "global");
        if (!gnutls_check_version(GNUTLS_CHECK_VERSION))
            throw Properties("error", "Bad GnuTLS version").add("version required", GNUTLS_CHECK_VERSION);
        gnutls_global_set_audit_log_function(Plugin::log);
        this->_loadConfiguration();
        this->_loadPrivateKey();
        this->_loadCertificate();
        this->_loadDHParams();
        ASSERT_INIT(gnutls_certificate_allocate_credentials(&this->x509_cred), "credentials");
        ASSERT(gnutls_certificate_set_x509_key(this->x509_cred, &this->crt, 1, this->key));
        ASSERT_INIT(gnutls_priority_init(&this->priority, this->priorityStrings.data(), &err_pos), "priority");
        gnutls_certificate_set_dh_params(this->x509_cred, this->dhParams);
    }
    catch (Properties p)
    {
        if (err_pos)
            p.add("error position", err_pos).add("priority string", this->priorityStrings);
        LOG_FATAL("Unable to initialize GnuTLS", p.toMap(), "Plugin", "onLoad");
        this->_deinit();
        return (false);
    }
    this->api->contexts().declareInstance("handshake", (this->handshake = new Handshake(this->api, this->handshakeTimeout)));
    this->api->contexts().declareInstance("record", (this->record = new Record(this->api)));
    return (true);
}
示例#2
0
void    Plugin::_loadPrivateKey()
{
    QFile           file(this->keyFile);
    int             bits;
    size_t          size;
    QByteArray      data;
    gnutls_datum_t  datum;
    int             error;

    if (!file.open(QIODevice::ReadWrite))
        throw Properties("error", "Unable to open the private key file").add("file", this->keyFile);
    ASSERT_INIT(gnutls_x509_privkey_init(&this->key), "privkey");
    // Checks that the private key is valid
    if (file.size() > 0)
    {
        data = file.readAll();
        datum.size = data.size();
        datum.data = (unsigned char *)data.data();
        if ((error = gnutls_x509_privkey_import_pkcs8(this->key, &datum, GNUTLS_X509_FMT_PEM, this->keyPassword.data(), 0)) != GNUTLS_E_SUCCESS)
        {
            LOG_ERROR("Invalid private key", Properties("error", gnutls_strerror(error)).toMap(), "Plugin", "_generatePrivateKey");
            file.resize(0);
        }
        else if (gnutls_x509_privkey_sec_param(this->key) != this->secParam)
            file.resize(0);
    }
    // Generates the private key
    if (file.size() == 0)
    {
        bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_RSA, this->secParam);
        LOG_INFO("Generating a new private key", Properties("secParam", gnutls_sec_param_get_name(this->secParam)).add("bits", bits).toMap(), "Plugin", "_generatePrivateKey");
        ASSERT(gnutls_x509_privkey_generate(this->key, GNUTLS_PK_RSA, bits, 0));
        ASSERT(gnutls_x509_privkey_verify_params(this->key));
        size = bits;
        data.resize((int)size);
        ASSERT(gnutls_x509_privkey_export_pkcs8(this->key, GNUTLS_X509_FMT_PEM, this->keyPassword.data(), GNUTLS_PKCS_USE_PBES2_AES_256, data.data(), &size));
        data.resize((int)size);
        file.write(data);
    }
}
示例#3
0
void    Plugin::_loadDHParams()
{
    QByteArray      data;
    QFile           file(this->dhParamsFile);
    int             bits;
    gnutls_datum_t  datum;
    int             error;

    if (!file.open(QIODevice::ReadWrite))
        throw Properties("error", "Unable to open the Diffie-Hellman parameters file").add("file", this->dhParamsFile);
    bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, this->secParam);
    ASSERT_INIT(gnutls_dh_params_init(&this->dhParams), "dh_params");
    // The Diffie-Hellman parameters expired
    if (QFileInfo(file).lastModified() < this->dhParamsExpiration)
        file.resize(0);
    // Import the DH parameters from the PEM file
    if (file.size() > 0)
    {
        data = file.readAll();
        datum.data = (unsigned char *)data.data();
        datum.size = data.size();
        if (gnutls_dh_params_import_pkcs3(this->dhParams, &datum, GNUTLS_X509_FMT_PEM) != GNUTLS_E_SUCCESS)
            file.resize(0);
    }
    // Generates the DH parameters and store them in a PEM file
    if (file.size() == 0)
    {
        LOG_INFO("Generating new Diffie-Hellman parameters. This might take some time.", Properties("secParam", gnutls_sec_param_get_name(this->secParam)).add("bits", bits).toMap(), "Plugin", "_generateDHParams");
        data.resize(bits);
        datum.data = (unsigned char *)data.data();
        datum.size = bits;
        ASSERT(gnutls_dh_params_generate2(this->dhParams, bits));
        size_t size = datum.size;
        ASSERT(gnutls_dh_params_export_pkcs3(this->dhParams, GNUTLS_X509_FMT_PEM, datum.data, &size));
        file.write(data.data(), size);
    }
}
示例#4
0
void Agc_sweep(SEGCTLPTR *heap_segments)
{
  SEGCTLPTR segctlp, *segctlpp;
  ELPTR elp;
  CODEDPTR *elpp;
  
  GC_SWEEP();

  for ( segctlpp = heap_segments; (segctlp = *segctlpp) != NIL; )
    /*  At end of loop so it can be skipped by continue: segctlpp = &((segctlp)->next ) */
  {
    PTR		elstart, elend;
    BITMAPPTR	bitmap = segctlp->bitmap;
    PTR		old_elend;
    ASSERT_DECL( PTR last_freestart )


      REPORT6(5,"Agc_collect{free list reconstruct}: segctlp=0x%p, elsize=%d, start=0x%p, end=0x%p, size=%d,els=%d\n",
	      (void *)segctlp,SEGELSIZE(segctlp),(void *)SEGSTART(segctlp),(void *)SEGEND(segctlp),SEGSIZE(segctlp),SEGELS(segctlp));


    /*
     ** First, clear bitmap (to indicate unused) from free list.
     ** This is essential for the freelist reconstruction algorithm to work.
     ** It ensures that all free list elements are enclosed in an unused heap area
     ** as identified by the bitmap.
     */

    /*
     ** Note that sweeping algorithm relies on the fact that the free list elements are
     ** in ascending address order, and there is some allocated space between elements.
     */

    ASSERT(bitmap == segctlp->bitmap,Agc_collect,'bitmap' out of sync);
    ASSERT(TSTMARK(bitmap,SEGELS(segctlp)+0),Agc_collect,bitmap trailer clear);
    ASSERT(!TSTMARK(bitmap,SEGELS(segctlp)+1),Agc_collect,bitmap trailer set);
    ASSERT(TSTMARK(bitmap,SEGELS(segctlp)+2),Agc_collect,bitmap trailer clear);

    elpp = &segctlp->free;
    elp = DECODEPTR(*elpp);
    old_elend = SEGSTART( segctlp );
    ASSERT_INIT( last_freestart = SEGSTART(segctlp) - 1 );
    if ( elp != NIL )
    {
      elstart = (PTR)elp;
      elend = (PTR)ELEND( elp, segctlp );
		
      CHECK_EL( segctlp, elp, elend );
    }
    else
    {
      elstart = elend = (char *)(SEGEND( segctlp )) + 1; /* well beyond any free space */
    }
		
    for (;;)
    {
		
      PTR		freestart, freeend;
      SIZE	freed_bytes;
		
      ASSERT(elp == DECODEPTR(*elpp),Agc_collect,elpp and elp out of step);
		
      ASSERT(elp == NIL || ((PTR)elp >= (PTR)SEGSTART(segctlp) && (PTR)elp < (PTR)SEGEND(segctlp))
	     ,Agc_collect,elp not within segment);
      ASSERT(elp == NIL || ((PTR)ELEND(elp,segctlp) <= (PTR)SEGEND(segctlp))
	     ,Agc_collect,elp end not within segment);
      ASSERT(elp == NIL || elend > elstart,Agc_collect,empty free list element);
		
      /*
       ** First, set 'freestart' to be the start of either the next:
       **
       **	free space starting outside a free list element
       ** or
       **	free space starting at the start of a free list element
       **	but finishing beyond the end of that element
       ** or
       **	an adress beyond the end of the segment
       */
		
      SCAN_TO_CLR( freestart, segctlp, bitmap, old_elend, elstart );
		
      ASSERT( freestart > last_freestart,Agc_collect,not progressing in sweep);
      ASSERT_INIT( last_freestart = freestart );
		
      if ( freestart >= SEGEND( segctlp ) ) break;
		
      while ( freestart == elstart && TSTMARK( bitmap, ELNUM( elend, segctlp ) ) )
      {
	/*
	 ** Freespace is identical to free list element.
	 ** Skip on to next free list element.
	 */
		
	ASSERT(freestart <= SEGEND(segctlp),Agc_collect,freestart beyond segend);
		
	/* step on to next free list element */
		
	ASSERT(elp != NIL,Agc_collect,elp nil at elpp update);
	elpp = &elp->next;
	elp = DECODEPTR(*elpp);
	old_elend = elend;
	if ( elp != NIL )
	{
	  elstart = (PTR)elp;
	  elend = (PTR)ELEND( elp, segctlp );

	  CHECK_EL( segctlp, elp, elend );
		
	  ASSERT(elend > elstart,Agc_collect,empty free list element);
	}
	else
	{
	  elstart = elend = (char *)(SEGEND( segctlp )) + 1; /* well beyond any free space */
	}
	ASSERT(old_elend < elstart,Agc_collect,free list not in order);
		
	SCAN_TO_CLR( freestart, segctlp, bitmap, old_elend, elstart );
      }
		
      if ( freestart >= SEGEND( segctlp ) ) break;
		
      ASSERT(freestart == (PTR)SEGSTART( segctlp ) || freestart > old_elend,Agc_collect,freestart before old_elend);
		
      ASSERT(freestart <= elstart,Agc_collect,freestart > elstart);
		
      ASSERT(elp == NIL || elstart == (PTR)DECODEPTR(*elpp),Agc_collect,elstart != *elpp);
		
		
      /*
       ** Secondly, set 'freeend' to be the end of the freespace
       */

      if ( freestart < elstart )
      {
	SCAN_TO_SET( freeend, segctlp, bitmap, freestart, elstart );
		
	freed_bytes = (char *)freeend - (char *)freestart;
	CLR_AT_FREE( freestart, SEGELSIZE(segctlp), freed_bytes );
      }
      else
      {
	ASSERT(freestart == elstart,Agc_collect,freestart == elstart);
		
	freed_bytes = 0;
	freeend = freestart;
      }

      while ( freeend == elstart )
      {
	/* step on to next free list element */
		
	ASSERT(freeend <= SEGEND(segctlp),Agc_collect,freeend beyond segend);
		
	elp = DECODEPTR(elp->next);
	old_elend = elend;
		
	if ( elp != NIL )
	{
	  elend = (PTR)ELEND( elp, segctlp );
	  CLR_ELHEADER_AT_FREE( (ELPTR)elstart, SEGELSIZE(segctlp) );
	  elstart = (PTR)elp;
		
	  CHECK_EL( segctlp, elp, elend );
		
	  ASSERT(elend > elstart,Agc_collect,empty free list element);
	}
	else
	{
	  CLR_ELHEADER_AT_FREE( (ELPTR)elstart, SEGELSIZE(segctlp) );
	  elstart = elend = (char *)(SEGEND( segctlp )) + 1; /* well beyond any free space */
	}
	ASSERT(old_elend < elstart,Agc_collect,free list not in order);
		
	ASSERT(freeend < elstart,Agc_collect,freeend not less than elstart);
		
	SCAN_TO_SET( freeend, segctlp, bitmap, old_elend, elstart );
		
	ASSERT(freeend >= old_elend,Agc_collect,freeend before old_elend);
	ASSERT(freeend <= elstart,Agc_collect,freeend beyond elstart limit);
	ASSERT(freeend <= SEGEND(segctlp),Agc_collect,freeend beyond segend);
		
	if ( freeend != old_elend )
	{
	  freed_bytes += (char *)freeend - (char *)old_elend;
	  CLR_AT_FREE( old_elend, SEGELSIZE(segctlp), (char *)freeend-(char *)old_elend );
	}
      }
		
      ASSERT(freeend < elstart,Agc_collect,freeend beyond elstart);
		
		
      /* freestart -> freeend is the new element */
      /* elp is freelist element beyond freeend, or NIL */
      /* elpp points to el pointer before freestart */
		
      ASSERT(freeend > freestart,Agc_collect,empty bitmap area);
      ASSERT(elp == NIL || (PTR)elp > freeend,Agc_collect,elp before freeend);
      ASSERT(freeend <= SEGEND(segctlp),Agc_collect,freeend beyond segend);
		
      ASSERT((PTR)elpp < freestart,Agc_collect,elpp beyond freestart);

      ASSERT(bitmap == segctlp->bitmap,Agc_collect,'bitmap' out of sync);
      ASSERT(TSTMARK(bitmap,SEGELS(segctlp)+0),Agc_collect,bitmap trailer clear);
      ASSERT(!TSTMARK(bitmap,SEGELS(segctlp)+1),Agc_collect,bitmap trailer set);
      ASSERT(TSTMARK(bitmap,SEGELS(segctlp)+2),Agc_collect,bitmap trailer clear);
		
      if ( freestart == SEGSTART( segctlp ) && freeend == SEGEND( segctlp ) )
      {
	/* Whole segment is free */
	/* +++ put segment at end of list rather than freeing */
		
	REPORT1(3,"Agc_collect: freeing seg=0x%p\n",(void *)segctlp);
		
	ASSERT(bitmap == segctlp->bitmap,Agc_collect,'bitmap' out of sync);

	FREE_BITMAP( bitmap, SEGELS( segctlp ) + 3 );
		
	ASSERT_INIT( segctlp->bitmap = bitmap = NIL );
		
	*segctlpp = segctlp->next; /* remove segctlp from list */
		
	Agc_b_allocated -= freed_bytes;
	Agc_s_grabbed--;
	Agc_b_grabbed -= SEGSIZE(segctlp);
		
	REP_DO(Agc_s_freed++);
		
	FREE_SEG( segctlp );
		
	ASSERT_INIT( segctlp = NIL );
		
	goto sweep_next_seg;
      }
      else if ( ELPTRENOUGH( freestart, freeend ) )
      {
#define				freeelp	((ELPTR)freestart)
		
	/* care needed because of possible overlap between new and old element header */
		
	REPORT5(6,"Agc_collect: adding free list element (0x%p -> 0x%p : size %d) after elpp 0x%p, before 0x%p\n",
		(void *)freestart,(void *)freeend,(char *)freeend-(char *)freestart,(void *)elpp,(void *)elp);
		
	ASSERT( IS_CLR(freestart,SEGELSIZE(segctlp),(char *)freeend-(char *)freestart)
	       ,Agc_collect,recreated free list element not clear);
		
	ASSERT( ((char *)freeend - (char *)freestart) % SEGELSIZE( segctlp ) == 0,Agc_collect,space recovered not multiple of elsize);
		
	freeelp->next = ENCODEPTR( elp );
	freeelp->elements = ((char *)freeend - (char *)freestart) / SEGELSIZE( segctlp );
		
	ASSERT(DECODEPTR(*elpp) == NIL || (PTR)DECODEPTR(*elpp) >= freestart,Agc_collect,discarding space already in free list);
		
	*elpp = ENCODEPTR( freestart );
		
	/* elp is still correct as next element, we have just inserted preceding it */
	/* however elpp now needs to point at new element */
	elpp = &freeelp->next;
		
	Agc_b_allocated -= freed_bytes;
		
	ASSERT( freeend == (PTR)ELEND(freeelp,segctlp)
	       ,Agc_collect,freeend not ELEND);
	ASSERT( freeelp->next == CODEDNIL || DECODEPTR(freeelp->next) > ELEND(freeelp,segctlp)
	       ,Agc_collect,free list elements overlap);
	ASSERT( freeelp->next == CODEDNIL || (PTR)DECODEPTR(freeelp->next) > freeend
	       ,Agc_collect,freeelp->next not past freeend);
		
#undef				freeelp
      }
      /* else ( ! ELPTRENOUGH( freestart, freeend ) )			*/
      /* 	do nothing, forget the few bytes of free space we found */
		
      old_elend = freeend;
		
    }

#ifdef	A_DEBUG
    if ( ELPTRENOUGH( (PTR)NIL, (char *)NIL+SEGELSIZE(segctlp) ) )
      /* if ( SEGELSIZE(segctlp) >= sizeof( EL ) ) */
    {
      SIZE	i;

      elp = DECODEPTR( segctlp->free );

      for ( i = 0; i < SEGELS(segctlp); i++ )
      {
	if ( !TSTMARK(bitmap,i) )
	{
	  while ( i > ELNUM( ELEND( elp, segctlp ), segctlp ) )
	  {
	    elp = DECODEPTR( elp->next );
	    ASSERT( elp != NIL,Agc_collect,free element beyond free list end at end of sweep);
	  }
	  ASSERT( i >= ELNUM( elp, segctlp ) && i < ELNUM( ELEND( elp, segctlp ), segctlp ),Agc_collect,free element not in free list at end of sweep);
	}
      }
    }
#endif

    ASSERT(bitmap == segctlp->bitmap,Agc_collect,'bitmap' out of sync);

    FREE_BITMAP( bitmap, SEGELS( segctlp ) + 3 );

    ASSERT_INIT( segctlp->bitmap = bitmap = NIL );

    segctlpp = &((segctlp)->next);

  sweep_next_seg:	;

  }

}
示例#5
0
void Agc_trace(
  SEGCTLPTR *heap_segments
)
{
  AREA    heap;
  AREA    area;			/* The current area being traced */
  TRACINGSTACK tstack;		/* Stack of areas to be traced */

  SEGCTLPTR segctlp;
  SEGCTLPTR *segctlpp;
  SIZE temp;

#ifndef	A_FUNNY_STEPAREAPTR	/* cop-out for weird architectures */
  {
    
	/* Check that STEPAREAPTR works correctly on this machine for this nastily aligned structure */
	/* If C compiler does tight packing, this could be a problem for the garbage collector */

	ASSERT_DECL( struct { PTR p1; char c; PTR p2; } *ass_struct = NIL )
	ASSERT_INIT( ( area.addr = (PTR)&ass_struct->c , area.size = sizeof(*ass_struct) ) );
	ASSERT_INIT( STEPAREA( area ) );
	ASSERT(area.addr == (PTR)&ass_struct->p2,Agc_collect,STEPAREA misbehaving);
  }
#endif

  heap.addr = SEGSTART( *heap_segments ); heap.size = 0 ;/* inital values to be improved in loop*/

  REPORT1(3, "%s\n", "Started trace... setting up bitmaps...");

  for ( segctlp = *heap_segments; segctlp != NIL; segctlp = segctlp->next )
  {
    REPORT6(6,"Agc_collect{mark}: segctlp=0x%p, elsize=%d, start=0x%p, end=0x%p, size=%d,els=%d\n",
	    (void *)segctlp,SEGELSIZE(segctlp),(void *)SEGSTART(segctlp),(void *)SEGEND(segctlp),SEGSIZE(segctlp),SEGELS(segctlp));

    if ( ! ( SEGELSIZE( segctlp ) > 0 && (char *)SEGEND( segctlp ) > (char *)SEGSTART( segctlp ) ) )
    {
      /* Segment control information has been corrupted. */
      /* Most likely this is because of a user scope/bound error, or CTRANS bug; though possibly a collector bug. */
      GC_ERROR(HEAP segments corrupt);
    }

    if ( (char *)SEGSTART( segctlp ) < (char *)(heap.addr) )
    {
      heap.size += (SIZE)((char *)(heap.addr) - (char *)SEGSTART( segctlp ));
      heap.addr = SEGSTART( segctlp );
    }
    
    if ( SEGEND( segctlp ) > (PTR)((char *)(heap.addr)+heap.size) )
      heap.size = (SIZE)((char *)SEGEND( segctlp ) - (char*)(heap.addr));

    GRAB_BITMAP( segctlp->bitmap, SEGELS( segctlp ) + 3 );
    SETMARK( segctlp->bitmap, SEGELS( segctlp ) + 0 );
    ASSERT(!TSTMARK(segctlp->bitmap,SEGELS(segctlp)+1),Agc_collect,bitmap trailer set at grab);
    SETMARK( segctlp->bitmap, SEGELS( segctlp ) + 2 );
    /* create an artificial endpoint which can be scanned to */
    REPORT2(6,"Agc_collect:\t\tbitmap, ptr=0x%p, size=%d\n", (void *)(segctlp->bitmap), SEGELS( segctlp ));
  }

  REPORT2(5,"Agc_collect: heap address=0x%p, heap size=%d\n",(void *)heap.addr,heap.size);

  INIT_STACK(tstack);
  ASSERT_INIT(PUSH(tstack,(PTR)Agc_collect,-42)); /* Assertion mark */
  PUSH(tstack, NIL, 0);				  /* identifies exhausted stack */

  REPORT1(3, "%s\n", "Initialising stack scan...");

  INIT_AREA(area);   /* set area to first area to search - could also PUSH
                        any additional areas (or use NEXT_AREA) */

  do
  {
    for ( ; !NILAREA(area); /* POP() at end of loop as it may contain statements */ )
    {

      REPORT3(6,"Agc_collect: AREA scan, ptr=0x%p -> 0x%p, size=%d\n",
	      (void *)area.addr,(void *)((char *)area.addr+area.size),area.size);

      ASSERT(area.size >= 0 && area.size < 100*1024*1024 /* 100Mb */,Agc_collect,area size not sensible);

      for ( ; area.size >= sizeof(PTR); STEPAREA(area) )
      {
	SIZE	els, el_in_seg;

	PTR p = * (PTR *) area.addr; /* View word as a pointer */

	REPORT3(9,"Agc_collect: AREA scan step, ptr=0x%p, size=%d, p=0x%p\n",
		(void *)area.addr,area.size,(void *)p);

	/* Continue loop if 'p' is unlikely to be a heap pointer.			*/
	/* Keeping the loop small may help some machines with small instruction caches.	*/

	if ( !VALIDPTR( p ) || !PTRINAREA(p,heap) ) continue;

	/* p is very likely to be a heap pointer */

	for ( segctlpp = heap_segments; (segctlp = *segctlpp) != NIL; segctlpp = &((segctlp)->next ))
	{
	  if ( (char *)p >= (char *)SEGSTART(segctlp) && (char *)p < (char *)SEGEND(segctlp) )
	  {
	    /* Segment for heap pointer */

	    goto found_segment;
	  }
	}

	/* Not a valid heap pointer */

	continue;		/* back to STEPAREA loop */

      found_segment:

	REPORT3(6,"Agc_collect, found_segment: ptr=0x%p, segctlp=0x%p, elsize=%d\n",
		(void *)p,(void *)segctlp,SEGELSIZE(segctlp));

	/*
	 **  	Move segment to front of segment list, to effect a 'cacheing' as in allocation.
	 **	We believe that there is locality in types of heap pointers,
	 **	(consider lists and trees) so it is likely that next
	 **	lookup will immediately succeed.
	 **	However a fast search startegy might be better ???
	 **
	 **	Note that typical programs only have a small number of segs,
	 **	many of which are infrequently used.
	 **		Multics Algol68 compiler uses 12 segs;
	 **		ELLA uses ??? segs.
	 */

	*segctlpp = segctlp->next;
	segctlp->next = *heap_segments;
	*heap_segments = segctlp;


#ifdef  MUST_POINT_TO_WORD
	/*
	 * Ignore pointers that are not word aligned,
	 * unless in a segment of objects of size that is not a multiple of word.
	 */

	if ( (SEGELSIZE(segctlp) & (WORDSIZE-1)) == 0 && (((CODEDPTR)(p) & (WORDSIZE-1)) != 0) )
	  continue;		/* p not to word aligned object, forget it */
#endif

#ifdef  MUST_POINT_TO_LWORD
	/*
	 * Ignore pointers that are not long word aligned,
	 * unless in a segment of objects of size that is not a multiple of long word.
	 */

	if ( (SEGELSIZE(segctlp) & (sizeof(long)-1)) == 0 && (((CODEDPTR)(p) & (sizeof(long)-1)) != 0) )
	  continue;		/* p not to long aligned object, forget it */
#endif


	IDENTIFY_ALIGN_EL( p, el_in_seg, segctlp );


#ifdef  MUST_POINT_TO_START
	/* Ignore pointers that point within objects	*/
	/* This could be implemented more efficiently	*/

	if ( p != * (PTR *) area.addr )
	  continue;		/* p not to start of element, forget it */
#endif

#ifdef	NO_GCMARK
	els = 1;
#else
	ANAL_DESC( els, p, area );
#endif

	REPORT3(6,"Agc_collect, aligned and analysed ptr: ptr=0x%p, element in seg=%d, elements=%d\n",
		(void *)p,el_in_seg,els);

#ifdef A_GC_HALFWORD_ALIGNED
      /* Interpret this as half word aligned (2byte) DJS 8/12/94 */
	/* +++ !!! ???
	 ** Crappy quick fix to keep elements word aligned for the Apollo
	 ** (also done for Sun/68000, though it has not been proved that this is necessary).
	 ** Apollo does not permit word objects to be aligned at any byte boundry,
	 ** even though 68020/68030 does.  This must be because C compiler generates
	 ** strange code, or page faults for words that straddle page boundries are
	 ** handled badly.
	 */

	if ( SEGELSIZE(segctlp) == 1 )
	{
	  if ( (long)p & 1 )
	  {
	    p--;
	    el_in_seg--;
	    els++;
	  }

	  if ( els & 1 )
	  {
	    els++;
	  }

	  if ( els <= 1 || els > SEGELS(segctlp) || p+(els*SEGELSIZE(segctlp)) > SEGEND(segctlp) )
	  {
	    els = 2;
	  }

	  REPORT3(6,"Agc_collect, adjusted to: ptr=0x%x, element in seg=%d, elements=%d\n",
		  p,el_in_seg,els);

	  goto els_sensible;
	}
#endif


#ifdef A_GC_WORD_ALIGNED

	/* +++ !!! ???
	 ** Crappy quick fix to keep elements word aligned.
	 */

	if ( SEGELSIZE(segctlp) == 1 )
	{
	  if ( !WORDALIGNED(p) )
	  {
	    int	offset = (int)((CODEDPTR)p & (WORDSIZE-1));
	    p = (char *)p - offset;
	    el_in_seg -= offset;
	    els += offset;
	  }

	  if ( !WORDALIGNED(els) )
	  {
	    els = (SIZE)ALIGN_NEXT(els,WORDSIZE);
	  }

	  if ( (els < WORDSIZE) || (els > SEGELS(segctlp)) || ((char *)p+(els*SEGELSIZE(segctlp)) > (char *)SEGEND(segctlp) ))
	  {
	    els = WORDSIZE;
	  }

	  REPORT3(6,"Agc_collect, adjusted to: ptr=0x%p, element in seg=%d, elements=%d\n",
		  (void *)p,el_in_seg,els);

	  goto els_sensible;
	}
#endif

	/* 'els' may be a very silly number, check it is reasonable	*/
	/* before doing arithmetic that may overflow.			*/

	if ( els <= 1 || els > SEGELS(segctlp) || (char *)p+(els*SEGELSIZE(segctlp)) > (char *)SEGEND(segctlp) )
	{
	  /* els = 1; assumed in case array descriptor mis analysed, the ptr is still valid */

	  if ( !TSTMARK( segctlp->bitmap, el_in_seg ) )
	  {
	    SETMARK( segctlp->bitmap, el_in_seg );

	    if ( SEGELSIZE(segctlp) >= PTRSIZE )
	    {
	      /* need only scan elements that are large enough to hold pointer */
	      PUSH( tstack, p, SEGELSIZE(segctlp) );

	      REPORT2(6,"Agc_collect: PUSH( ptr=0x%p, size=%d )\n",
		      (void *)p,SEGELSIZE(segctlp));
	    }
	  }
	}
	else
	{
	els_sensible:
	  CALCTSTMARKS( segctlp->bitmap, el_in_seg, els, temp );
	  if ( !RESTSTMARKS( segctlp->bitmap, el_in_seg, els, temp ) )
	  {
	    /*
	     ** At least one element in area has not been marked before.
	     **
	     ** We could just mark and push unmarked areas,
	     ** but this complicates logic for a fairly rare eventuality,
	     ** mainly caused by the trimming of heap rows.
	     */

	    SETMARKS( segctlp->bitmap, el_in_seg, els );

	    if ( SEGELSIZE(segctlp) >= PTRSIZE )
	    {
	      /* need only scan elements that are large enough to hold pointer */
	      PUSH( tstack, p, els*SEGELSIZE(segctlp) );

	      REPORT2(6,"Agc_collect: PUSH( ptr=0x%p, size=%d )\n",
		      (void *)p,els*SEGELSIZE(segctlp));
	    }
	  }
	}
      }
      area = POP(tstack);
    }
    /* Stack is exhausted, replace end marker */

    PUSH(tstack, NIL, 0);	/* identifies exhausted stack */

    NEXT_AREA(area);

    REPORT2(6,"Agc_collect: NEXT_AREA, ptr=0x%p, size=%d\n",(void *)area.addr,area.size);
  }
  while( area.addr != NIL );

  area = POP(tstack);		/* pop of (NIL, 0) to leave stack empty and tidy before calling FREE_STACK() */

  ASSERT_INIT( area=POP(tstack) );
  ASSERT(area.addr == (PTR)Agc_collect && area.size == -42,Agc_collect,tracing stack misuse);

  FREE_STACK(tstack);
  REPORT1(3, "%s\n", "End of trace");
}
示例#6
0
void update(void)
{
   ASSERT_INIT();
   ssd1306_update(&ssd);
}
示例#7
0
void clear(void)
{
   ASSERT_INIT();
   ssd1306_clear(&ssd);
}
示例#8
0
void invert(bool i)
{
   ASSERT_INIT();
   ssd1306_invert(&ssd, i);   
}
示例#9
0
void set_pixel(int16_t x, int16_t y, uint16_t color)
{
   ASSERT_INIT();
   ssd1306_set_pixel(&ssd, x, y, color);   
}
示例#10
0
void    Plugin::_loadCertificate()
{
    QFile            file(this->crtFile);
    gnutls_datum_t   datum;
    size_t           size = 2048;
    QByteArray       data;
    gnutls_privkey_t privkey;
    gnutls_pubkey_t  pubkey;
    gnutls_pubkey_t  pubkeyCrt;
    int              error;
    QMap<char *, QByteArray> oid;
    gnutls_digest_algorithm_t digest;

    if (!file.open(QIODevice::ReadWrite))
        throw Properties("error", "Unable to open the certificate file").add("file", this->crtFile);
    ASSERT_INIT(gnutls_x509_crt_init(&this->crt), "crt");
    ASSERT(gnutls_privkey_init(&privkey));
    ASSERT(gnutls_privkey_import_x509(privkey, this->key, 0));
    ASSERT(gnutls_pubkey_init(&pubkey));
    ASSERT(gnutls_pubkey_import_privkey(pubkey, privkey, 0, 0));
    // Verifies that the certificate is valid
    if (file.size() > 0)
    {
        ASSERT(gnutls_pubkey_init(&pubkeyCrt));
        data = file.readAll();
        datum.size = data.size();
        datum.data = (unsigned char *)data.data();
        if (gnutls_x509_crt_import(this->crt, &datum, GNUTLS_X509_FMT_PEM) != GNUTLS_E_SUCCESS)
            file.resize(0);
        else if (gnutls_x509_crt_get_expiration_time(this->crt) < ::time(NULL) + CRT_EXPIRATION_REGEN)
            file.resize(0);
        else if (gnutls_pubkey_import_x509(pubkeyCrt, this->crt, 0) != GNUTLS_E_SUCCESS)
            file.resize(0);
        // Ensures that the public keys of the certificate and the private key match
        size_t size1 = size, size2 = size;
        QByteArray pub1((int)size1, 0), pub2((int)size2, 0);
        if (gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_PEM, pub1.data(), &size1) != GNUTLS_E_SUCCESS
            || gnutls_pubkey_export(pubkeyCrt, GNUTLS_X509_FMT_PEM, pub2.data(), &size2) != GNUTLS_E_SUCCESS
            || size1 != size2 || pub1 != pub2)
            file.resize(0);
        gnutls_pubkey_deinit(pubkeyCrt);
    }
    // Generates a new certificate
    if (file.size() == 0)
    {
        gnutls_x509_crt_deinit(this->crt);
        this->init.removeAll("crt");
        ASSERT_INIT(gnutls_x509_crt_init(&this->crt), "crt");
        LOG_INFO("Generating a new certificate", "Plugin", "_generateCertificate");
        oid.insert((char *)GNUTLS_OID_X520_COMMON_NAME, "LightBird");
        oid.insert((char *)GNUTLS_OID_X520_ORGANIZATION_NAME, "LightBird");
        QMapIterator<char *, QByteArray> it(oid);
        while (it.hasNext())
            ASSERT(gnutls_x509_crt_set_dn_by_oid(this->crt, it.key(), 0, it.value().data(), it.next().value().size()));
        ASSERT(gnutls_x509_crt_set_pubkey(this->crt, pubkey));
        data = this->_generateSerial();
        ASSERT(gnutls_x509_crt_set_serial(this->crt, data.data(), data.size()));
        ASSERT(gnutls_x509_crt_set_activation_time(this->crt, ::time(NULL)));
        ASSERT(gnutls_x509_crt_set_expiration_time(this->crt, ::time(NULL) + CRT_EXPIRATION));
        ASSERT(gnutls_x509_crt_set_basic_constraints(this->crt, 0, -1));
        ASSERT(gnutls_x509_crt_set_key_purpose_oid(this->crt, GNUTLS_KP_TLS_WWW_SERVER, 0));
        ASSERT(gnutls_x509_crt_set_key_usage(this->crt, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT));
        data.resize((int)size);
        ASSERT(gnutls_x509_crt_get_key_id(this->crt, 0, (unsigned char *)data.data(), &size));
        ASSERT(gnutls_x509_crt_set_subject_key_id(this->crt, (unsigned char *)data.data(), size));
        ASSERT(gnutls_x509_crt_set_version(this->crt, 3));
        ASSERT(gnutls_pubkey_get_preferred_hash_algorithm(pubkey, &digest, NULL));
        ASSERT(gnutls_x509_crt_privkey_sign(this->crt, this->crt, privkey, digest, 0));
        size = data.size();
        ASSERT(gnutls_x509_crt_export(this->crt, GNUTLS_X509_FMT_PEM, data.data(), &size));
        data.resize((int)size);
        file.write(data);
    }
    gnutls_pubkey_deinit(pubkey);
    gnutls_privkey_deinit(privkey);
}