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); }
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); } }
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); } }
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: ; } }
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"); }
void update(void) { ASSERT_INIT(); ssd1306_update(&ssd); }
void clear(void) { ASSERT_INIT(); ssd1306_clear(&ssd); }
void invert(bool i) { ASSERT_INIT(); ssd1306_invert(&ssd, i); }
void set_pixel(int16_t x, int16_t y, uint16_t color) { ASSERT_INIT(); ssd1306_set_pixel(&ssd, x, y, color); }
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); }