// Verbosity level currently supports 0 (low), 1 (medium), 2 (high) // Buffer must be hold enough to hold the output string. See the source to get an idea of how many bytes will be output void RAK_DLL_EXPORT StatisticsToString( RakNetStatistics *s, char *buffer, int verbosityLevel ) { if ( s == 0 ) { sprintf( buffer, "stats is a NULL pointer in statsToString\n" ); return ; } if ( verbosityLevel == 0 ) { // Verbosity level 0 sprintf( buffer, "Total bytes sent: %u\n" "Total bytes received: %u\n" "Packetloss: %.1f%%\n", (unsigned int) BITS_TO_BYTES( s->totalBitsSent ), (unsigned int) BITS_TO_BYTES( s->bitsReceived + s->bitsWithBadCRCReceived ), 100.0f * ( float ) s->messagesTotalBitsResent / ( float ) s->totalBitsSent ); } else if ( verbosityLevel == 1 ) { RakNetTime time = RakNet::GetTime(); double elapsedTime; double bpsSent; double bpsReceived; elapsedTime = (time-s->connectionStartTime) / 1000.0f; bpsSent = (double) s->totalBitsSent / elapsedTime; bpsReceived= (double) s->bitsReceived / elapsedTime; // Verbosity level 1 sprintf( buffer, "Messages in Send buffer: %u\n" "Messages sent: %u\n" "Bytes sent: %u\n" "Acks sent: %u\n" "Acks in send buffer: %u\n" "Messages waiting for ack: %u\n" "Messages resent: %u\n" "Bytes resent: %u\n" "Packetloss: %.1f%%\n" "Messages received: %u\n" "Bytes received: %u\n" "Acks received: %u\n" "Duplicate acks received: %u\n" "Inst. KBits per second: %.1f\n" "KBits per second sent:\t\t\t%.1f\n" "KBits per second received:\t\t%.1f\n" "Bandwith exceeded:\t\t\t%i\n", s->messageSendBuffer[ SYSTEM_PRIORITY ] + s->messageSendBuffer[ HIGH_PRIORITY ] + s->messageSendBuffer[ MEDIUM_PRIORITY ] + s->messageSendBuffer[ LOW_PRIORITY ], s->messagesSent[ SYSTEM_PRIORITY ] + s->messagesSent[ HIGH_PRIORITY ] + s->messagesSent[ MEDIUM_PRIORITY ] + s->messagesSent[ LOW_PRIORITY ], (unsigned int) BITS_TO_BYTES( s->totalBitsSent ), s->acknowlegementsSent, s->acknowlegementsPending, s->messagesOnResendQueue, s->messageResends, (unsigned int) BITS_TO_BYTES( s->messagesTotalBitsResent ), 100.0f * ( float ) s->messagesTotalBitsResent / ( float ) s->totalBitsSent, s->duplicateMessagesReceived + s->invalidMessagesReceived + s->messagesReceived, (unsigned int) BITS_TO_BYTES( s->bitsReceived + s->bitsWithBadCRCReceived ), s->acknowlegementsReceived, s->duplicateAcknowlegementsReceived, s->bitsPerSecond / 1000.0, bpsSent / 1000.0, bpsReceived / 1000.0, s->bandwidthExceeded); } else { RakNetTime time = RakNet::GetTime(); double elapsedTime; double bpsSent; double bpsReceived; elapsedTime = (time-s->connectionStartTime) / 1000.0f; bpsSent = (double) s->totalBitsSent / elapsedTime; bpsReceived= (double) s->bitsReceived / elapsedTime; // Verbosity level 2. sprintf( buffer, "Bytes sent:\t\t\t\t%u\n" "Messages in send buffer:\t\tSP:%u HP:%u MP:%u LP:%u\n" "Messages sent:\t\t\t\tSP:%u HP:%u MP:%u LP:%u\n" "Message data bytes sent:\t\tSP:%u HP:%u MP:%u LP:%u\n" "Message header bytes sent:\t\tSP:%u HP:%u MP:%u LP:%u\n" "Message total bytes sent:\t\tSP:%u HP:%u MP:%u LP:%u\n" "Bytes received:\t\t\t\tTtl:%u Good:%u Bad:%u\n" "Packets received:\t\t\tTtl:%u Good:%u Bad:%u\n" "Acks received:\t\t\t\tTtl:%u Good:%u Dup:%u\n" "Messages received:\t\t\tTotal:%u Valid:%u Invalid:%u Dup:%u\n" "Packetloss:\t\t\t\t%.1f%%\n" "Packets sent:\t\t\t\t%u\n" "Acks sent:\t\t\t\t%u\n" "Acks in send buffer:\t\t\t%u\n" "Messages waiting for ack:\t\t%u\n" "Ack bytes sent:\t\t\t\t%u\n" "Sent packets containing only acks:\t%u\n" "Sent packets w/only acks and resends:\t%u\n" "Reliable messages resent:\t\t%u\n" "Reliable message data bytes resent:\t%u\n" "Reliable message header bytes resent:\t%u\n" "Reliable message total bytes resent:\t%u\n" "Number of messages split:\t\t%u\n" "Number of messages unsplit:\t\t%u\n" "Message splits performed:\t\t%u\n" "Additional encryption bytes:\t\t%u\n" "Sequenced messages out of order:\t%u\n" "Sequenced messages in order:\t\t%u\n" "Ordered messages out of order:\t\t%u\n" "Ordered messages in of order:\t\t%u\n" "Split messages waiting for reassembly:\t%u\n" "Messages in internal output queue:\t%u\n" "Inst KBits per second:\t\t\t%.1f\n" "Elapsed time (sec):\t\t\t%.1f\n" "KBits per second sent:\t\t\t%.1f\n" "KBits per second received:\t\t%.1f\n" "Bandwith exceeded:\t\t\t%i\n", (unsigned int) BITS_TO_BYTES( s->totalBitsSent ), s->messageSendBuffer[ SYSTEM_PRIORITY ], s->messageSendBuffer[ HIGH_PRIORITY ], s->messageSendBuffer[ MEDIUM_PRIORITY ], s->messageSendBuffer[ LOW_PRIORITY ], s->messagesSent[ SYSTEM_PRIORITY ], s->messagesSent[ HIGH_PRIORITY ], s->messagesSent[ MEDIUM_PRIORITY ], s->messagesSent[ LOW_PRIORITY ], (unsigned int) BITS_TO_BYTES( s->messageDataBitsSent[ SYSTEM_PRIORITY ] ), BITS_TO_BYTES( s->messageDataBitsSent[ HIGH_PRIORITY ] ), (unsigned int) BITS_TO_BYTES( s->messageDataBitsSent[ MEDIUM_PRIORITY ] ), (unsigned int) BITS_TO_BYTES( s->messageDataBitsSent[ LOW_PRIORITY ] ), (unsigned int) BITS_TO_BYTES( s->messageTotalBitsSent[ SYSTEM_PRIORITY ] - s->messageDataBitsSent[ SYSTEM_PRIORITY ] ), (unsigned int) BITS_TO_BYTES( s->messageTotalBitsSent[ HIGH_PRIORITY ] - s->messageDataBitsSent[ HIGH_PRIORITY ] ), (unsigned int) BITS_TO_BYTES( s->messageTotalBitsSent[ MEDIUM_PRIORITY ] - s->messageDataBitsSent[ MEDIUM_PRIORITY ] ), BITS_TO_BYTES( s->messageTotalBitsSent[ LOW_PRIORITY ] - s->messageDataBitsSent[ LOW_PRIORITY ] ), (unsigned int) BITS_TO_BYTES( s->messageTotalBitsSent[ SYSTEM_PRIORITY ] ), BITS_TO_BYTES( s->messageTotalBitsSent[ HIGH_PRIORITY ] ), (unsigned int) BITS_TO_BYTES( s->messageTotalBitsSent[ MEDIUM_PRIORITY ] ), (unsigned int) BITS_TO_BYTES( s->messageTotalBitsSent[ LOW_PRIORITY ] ), (unsigned int) BITS_TO_BYTES( s->bitsReceived + s->bitsWithBadCRCReceived ), BITS_TO_BYTES( s->bitsReceived ), (unsigned int) BITS_TO_BYTES( s->bitsWithBadCRCReceived ), s->packetsReceived + s->packetsWithBadCRCReceived, s->packetsReceived, s->packetsWithBadCRCReceived, s->acknowlegementsReceived + s->duplicateAcknowlegementsReceived, s->acknowlegementsReceived, s->duplicateAcknowlegementsReceived, s->messagesReceived + s->invalidMessagesReceived + s->duplicateMessagesReceived, s->messagesReceived, s->invalidMessagesReceived, s->duplicateMessagesReceived, 100.0f * ( float ) s->messagesTotalBitsResent / ( float ) s->totalBitsSent, s->packetsSent, s->acknowlegementsSent, s->acknowlegementsPending, s->messagesOnResendQueue, (unsigned int) BITS_TO_BYTES( s->acknowlegementBitsSent ), s->packetsContainingOnlyAcknowlegements, s->packetsContainingOnlyAcknowlegementsAndResends, s->messageResends, (unsigned int) BITS_TO_BYTES( s->messageDataBitsResent ), (unsigned int) BITS_TO_BYTES( s->messagesTotalBitsResent - s->messageDataBitsResent ), (unsigned int) BITS_TO_BYTES( s->messagesTotalBitsResent ), s->numberOfSplitMessages, s->numberOfUnsplitMessages, s->totalSplits, (unsigned int) BITS_TO_BYTES( s->encryptionBitsSent ), s->sequencedMessagesOutOfOrder, s->sequencedMessagesInOrder, s->orderedMessagesOutOfOrder, s->orderedMessagesInOrder, s->messagesWaitingForReassembly, s->internalOutputQueueSize, s->bitsPerSecond/1000.0, elapsedTime, bpsSent / 1000.0, bpsReceived / 1000.0, s->bandwidthExceeded ); } }
/* * saveImageFile - saves a cursor or icon file */ static bool saveImageFile( img_node *node ) { BITMAPARRAYFILEHEADER2 new_file; BITMAPFILEHEADER2 *and_part; BITMAPFILEHEADER2 *xor_part; BITMAPINFO2 *andbmi; BITMAPINFO2 *xorbmi; long clrtable_size; long and_size; ULONG nextoff; RGB2 *colours; FILE *fp; char text[ HINT_TEXT_LEN ]; char filename[ _MAX_FNAME ]; img_node *new_image; bool ok; ok = false; fp = fopen( node->fname, "wb" ); if( fp != NULL ) { if( fseek( fp, 0L, SEEK_SET ) == 0 ) { ok = true; nextoff = 0; for( new_image = node; new_image != NULL; new_image = new_image->nexticon ) { new_file.usType = BFT_BITMAPARRAY; new_file.cbSize = sizeof( BITMAPARRAYFILEHEADER2 ); new_file.offNext = nextoff; new_file.cxDisplay = 0; new_file.cyDisplay = 0; and_part = fillFileHeader( new_image ); memcpy( &(new_file.bfh2), and_part, sizeof( BITMAPFILEHEADER2 ) ); /* * First the info for the AND mask */ andbmi = GetAndBitmapInfo( new_image ); if( andbmi == NULL ) { ok = false; } else { clrtable_size = sizeof( RGB2 ) * ( 1 << new_image->bitcount ); and_size = sizeof( RGB2 ) * 2; new_file.bfh2.offBits = new_file.offNext + new_file.cbSize + and_size + clrtable_size + sizeof( BITMAPFILEHEADER2 ); memcpy( &(new_file.bfh2.bmp2), andbmi, sizeof( BITMAPINFOHEADER2 ) ); colours = (void *)&(andbmi->argbColor[0]); if( fwrite( &new_file, sizeof( BITMAPARRAYFILEHEADER2 ), 1, fp ) != 1 ) { ok = false; } else if( fwrite( colours, and_size, 1, fp ) != 1 ) { ok = false; } FreeDIBitmapInfo( andbmi ); } MemFree( and_part ); if( ok ) { /* * Now we write the XOR part */ xor_part = fillFileHeader( new_image ); xorbmi = GetXorBitmapInfo( new_image ); if( xorbmi == NULL ) { ok = false; } else { xor_part->offBits = new_file.bfh2.offBits + BITS_TO_BYTES( new_image->width, 2 * new_image->height ); memcpy( &(xor_part->bmp2), xorbmi, sizeof( BITMAPINFOHEADER2 ) ); colours = (void *)&(xorbmi->argbColor[0]); if( fwrite( xor_part, sizeof( BITMAPFILEHEADER2 ), 1, fp ) != 1 ) { ok = false; } else if( fwrite( colours, clrtable_size, 1, fp ) != 1 ) { ok = false; } FreeDIBitmapInfo( xorbmi ); } MemFree( xor_part ); nextoff = nextoff + sizeof( BITMAPARRAYFILEHEADER2 ) + and_size + sizeof( BITMAPFILEHEADER2 ) + clrtable_size; } if( !rc ) { break; } } } fclose( fp ); } if( ok ) { /* * Now we write the bits for all the images in the file. */ if( !writeImageBits( fp, node ) ) { return( false ); } AllowRestoreOption( node ); SetIsSaved( node->hwnd, TRUE ); GetFnameFromPath( node->fname, filename ); if( node->imgtype == ICON_IMG ) { sprintf( text, "Icon saved to '%s'", filename ); } else { sprintf( text, "Pointer saved to '%s'", filename ); } SetHintText( text ); } return( ok ); } /* saveImageFile */
/* * Loop thru arts[] array marking state of each article READ/UNREAD */ void parse_unread_arts( struct t_group *group) { int i; long unread = 0; long bitmin, bitmax; t_bitmap *newbitmap = (t_bitmap *) 0; bitmin = group->newsrc.xmin; bitmax = group->newsrc.xmax; /* * TODO * what about group->newsrc.xmax > group->xmax? * that should indicate an artnum 'reset' on the server * (or using the "wrong" newsrc for that server) */ if (group->xmax > group->newsrc.xmax) group->newsrc.xmax = group->xmax; if (group->newsrc.xmax >= bitmin) { newbitmap = my_malloc(BITS_TO_BYTES(group->newsrc.xmax - bitmin + 1)); NSETRNG0(newbitmap, 0L, group->newsrc.xmax - bitmin); } for_each_art(i) { if (arts[i].artnum < bitmin) arts[i].status = ART_READ; else if (arts[i].artnum > bitmax) arts[i].status = ART_UNREAD; else if (NTEST(group->newsrc.xbitmap, arts[i].artnum - bitmin) == ART_READ) arts[i].status = ART_READ; else arts[i].status = ART_UNREAD; /* TODO: logic correct? */ if (newbitmap != NULL && arts[i].status == ART_UNREAD && arts[i].artnum >= bitmin) { #if 0 /* * check for wrong article numbers in the overview * * TODO: check disabled as we currently catch the artnum > high_mark * case in read_nov_file() where we might be able to * fix the broken artnum (via xref:-parsing). currently * we just skip the art there. */ if (arts[i].artnum <= group->xmax) #endif /* 0 */ NSET1(newbitmap, arts[i].artnum - bitmin); unread++; } } group->newsrc.xbitlen = group->newsrc.xmax - bitmin + 1; FreeIfNeeded(group->newsrc.xbitmap); group->newsrc.xbitmap = newbitmap; group->newsrc.num_unread = unread; }
void FileListTransfer::Send(FileList *fileList, RakPeerInterface *rakPeer, PlayerID recipient, unsigned short setID, PacketPriority priority, char orderingChannel, bool compressData) { RakNet::BitStream outBitstream, encodedData; HuffmanEncodingTree tree; unsigned int frequencyTable[ 256 ]; unsigned int i,j; unsigned totalCompressedLength, totalLength; DataStructures::Queue<FileListNode> compressedFiles; FileListNode n; if (compressData) { memset(frequencyTable,0,256*sizeof(unsigned int)); for (i=0; i < fileList->fileList.Size(); i++) { for (j=0; j < fileList->fileList[i].dataLength; j++) { ++frequencyTable[(unsigned char)(fileList->fileList[i].data[j])]; } } tree.GenerateFromFrequencyTable(frequencyTable); // Compress all the files, so we know the total compressed size to be sent totalCompressedLength=totalLength=0; for (i=0; i < fileList->fileList.Size(); i++) { encodedData.Reset(); // Why send compressed chunks if we are not sending the whole file? assert(fileList->fileList[i].fileLength==fileList->fileList[i].fileLength); tree.EncodeArray((unsigned char*)fileList->fileList[i].data, fileList->fileList[i].dataLength, &encodedData); n.dataLength=encodedData.GetNumberOfBitsUsed(); totalCompressedLength+=BITS_TO_BYTES(n.dataLength); totalLength+=fileList->fileList[i].fileLength; n.data = new char[BITS_TO_BYTES(n.dataLength)]; memcpy(n.data, encodedData.GetData(), BITS_TO_BYTES(n.dataLength)); compressedFiles.Push(n); } } // Write the chunk header, which contains the frequency table, the total number of files, and the total number of bytes bool anythingToWrite; outBitstream.Write((unsigned char)ID_FILE_LIST_TRANSFER_HEADER); outBitstream.Write(setID); anythingToWrite=fileList->fileList.Size()>0; outBitstream.Write(anythingToWrite); if (anythingToWrite) { if (compressData) { outBitstream.Write(true); for (i=0; i < 256; i++) outBitstream.WriteCompressed(frequencyTable[i]); outBitstream.WriteCompressed(fileList->fileList.Size()); outBitstream.WriteCompressed(totalLength); outBitstream.WriteCompressed(totalCompressedLength); } else { outBitstream.Write(false); outBitstream.WriteCompressed(fileList->fileList.Size()); outBitstream.WriteCompressed(totalLength); } rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); // Send each possibly compressed file for (i=0; i < compressedFiles.Size(); i++) { outBitstream.Reset(); outBitstream.Write((unsigned char)ID_FILE_LIST_TRANSFER_FILE); outBitstream.Write(fileList->fileList[i].context); outBitstream.Write(setID); outBitstream.WriteCompressed(i); outBitstream.WriteCompressed(fileList->fileList[i].dataLength); // Original length if (compressData) outBitstream.WriteCompressed(compressedFiles[i].dataLength); // Compressed bitlength } stringCompressor->EncodeString(fileList->fileList[i].filename, 512, &outBitstream); if (compressData) { outBitstream.WriteBits((const unsigned char*)compressedFiles[i].data, compressedFiles[i].dataLength); delete [] compressedFiles[i].data; } else outBitstream.WriteBits((const unsigned char*)fileList->fileList[i].data, fileList->fileList[i].dataLength); rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); } } else rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); }
//void possect_add_old(u32 key, const Pvoid_t tokens); void possect_add(const Pvoid_t tokens) { static char *posbuf; static char *xidbuf; if (!posbuf){ posbuf = xmalloc(iblock_size * 8 + 8); memset(posbuf, 0, iblock_size * 8 + 8); xidbuf = xmalloc((iblock_size * 2 + 3) * 8); memset(xidbuf, 0, (iblock_size * 2 + 3) * 8); } Word_t *ptr; u32 len, xoffs, poffs, prev_offs, prev_xid, xsum, xmax, osum, omax; Word_t xid = poffs = prev_offs = prev_xid =\ xsum = osum = osum = omax = xmax = len = 0; JLF(ptr, tokens, xid); while (ptr){ growing_glist *g = (growing_glist*)*ptr; *ptr = poffs; rice_encode(posbuf, &poffs, g->lst.lst, g->lst.len); free(g); xsum += xid - prev_xid; osum += poffs - prev_offs; if (xid - prev_xid > xmax) xmax = xid - prev_xid; if (poffs - prev_offs > omax) omax = poffs - prev_offs; prev_xid = xid; prev_offs = poffs; ++len; JLN(ptr, tokens, xid); } poffs = BITS_TO_BYTES(poffs); xid = prev_xid = prev_offs = xoffs = 0; elias_gamma_write(xidbuf, &xoffs, len + 1); if (!len) goto write_buffers; u32 rice_f1 = estimate_rice_f_param(xsum, xmax, len); u32 rice_f2 = estimate_rice_f_param(osum, omax, len); rice_write(xidbuf, &xoffs, rice_f1, 2); rice_write(xidbuf, &xoffs, rice_f2, 2); JLF(ptr, tokens, xid); while (ptr){ rice_write(xidbuf, &xoffs, xid - prev_xid, rice_f1); prev_xid = xid; rice_write(xidbuf, &xoffs, *ptr - prev_offs, rice_f2); prev_offs = *ptr; JLN(ptr, tokens, xid); } write_buffers: xoffs = BITS_TO_BYTES(xoffs); toc_e toc; toc.offs = ftello64(data_f); toc.val = xoffs; fwrite(&toc, sizeof(toc_e), 1, toc_f); fwrite(xidbuf, xoffs, 1, data_f); fwrite(posbuf, poffs, 1, data_f); memset(xidbuf, 0, xoffs); memset(posbuf, 0, poffs); }
PluginReceiveResult Router::OnReceive(Packet *packet) { if (packet->data[0]==ID_ROUTE_AND_MULTICAST || (packet->length>5 && packet->data[0]==ID_TIMESTAMP && packet->data[5]==ID_ROUTE_AND_MULTICAST)) { #ifdef _DO_PRINTF RAKNET_DEBUG_PRINTF("%i got routed message from %i\n", peer->GetExternalID(packet->systemAddress).port, packet->systemAddress.port); #endif RakNetTime timestamp; PacketPriority priority; PacketReliability reliability; unsigned char orderingChannel; SystemAddress originalSender; RakNet::BitStream out; BitSize_t outStartingOffset; unsigned int payloadBitLength; unsigned payloadWriteByteOffset; RakNet::BitStream incomingBitstream(packet->data, packet->length, false); incomingBitstream.IgnoreBits(8); if (packet->data[0]==ID_TIMESTAMP) { incomingBitstream.Read(timestamp); out.Write((MessageID)ID_TIMESTAMP); out.Write(timestamp); incomingBitstream.IgnoreBits(8); } // Read the send parameters unsigned char c; incomingBitstream.ReadCompressed(c); priority=(PacketPriority)c; incomingBitstream.ReadCompressed(c); reliability=(PacketReliability)c; incomingBitstream.ReadCompressed(orderingChannel); incomingBitstream.Read(payloadBitLength); out.Write((MessageID)ID_ROUTE_AND_MULTICAST); out.WriteCompressed((unsigned char)priority); out.WriteCompressed((unsigned char)reliability); out.WriteCompressed((unsigned char)orderingChannel); out.Write(payloadBitLength); out.AlignWriteToByteBoundary(); incomingBitstream.AlignReadToByteBoundary(); payloadWriteByteOffset=(unsigned int) BITS_TO_BYTES(out.GetWriteOffset()); out.Write(&incomingBitstream, payloadBitLength); // This write also does a read on incomingBitStream if (restrictByType) { RakNet::BitStream t(out.GetData()+payloadWriteByteOffset, sizeof(unsigned char), false); MessageID messageID; t.Read(messageID); if (allowedTypes.HasData(messageID)==false) return RR_STOP_PROCESSING_AND_DEALLOCATE; // Don't route restricted types } incomingBitstream.Read(originalSender); out.Write(originalSender); outStartingOffset=out.GetWriteOffset(); // Deserialize the root bool hasData=false; SystemAddress recipient; unsigned short numberOfChildren; incomingBitstream.Read(hasData); incomingBitstream.Read(recipient); // This should be our own address if (incomingBitstream.ReadCompressed(numberOfChildren)==false) { #ifdef _DEBUG RakAssert(0); #endif return RR_STOP_PROCESSING_AND_DEALLOCATE; } unsigned childIndex; bool childHasData=false; SystemAddress childRecipient; unsigned short childNumberOfChildren; SystemAddress immediateRecipient; immediateRecipient=UNASSIGNED_SYSTEM_ADDRESS; int pendingNodeCount=0; for (childIndex=0; childIndex < numberOfChildren; childIndex++) { while (pendingNodeCount!=-1) { // Copy out the serialized subtree for this child incomingBitstream.Read(childHasData); incomingBitstream.Read(childRecipient); if (!incomingBitstream.ReadCompressed(childNumberOfChildren)) return RR_STOP_PROCESSING_AND_DEALLOCATE; if (immediateRecipient==UNASSIGNED_SYSTEM_ADDRESS) { immediateRecipient=childRecipient; } pendingNodeCount+=childNumberOfChildren-1; out.Write(childHasData); out.Write(childRecipient); out.WriteCompressed(childNumberOfChildren); } #ifdef _DO_PRINTF RAKNET_DEBUG_PRINTF("%i routing to %i\n", peer->GetExternalID(packet->systemAddress).port, immediateRecipient.port); #endif // Send what we got so far SendUnified(&out, priority, reliability, orderingChannel, immediateRecipient, false); // Restart writing the per recipient data out.SetWriteOffset(outStartingOffset); // Reread the top level node immediateRecipient=UNASSIGNED_SYSTEM_ADDRESS; pendingNodeCount=0; } // Write the user payload to the packet struct if this is a destination and change the sender and return true if (hasData) { #ifdef _DO_PRINTF RAKNET_DEBUG_PRINTF("%i returning payload to user\n", peer->GetExternalID(packet->systemAddress).port); #endif if (packet->data[0]==ID_TIMESTAMP ) { memcpy( packet->data + sizeof(RakNetTime)+sizeof(unsigned char), out.GetData()+payloadWriteByteOffset, BITS_TO_BYTES(payloadBitLength) ); packet->bitSize=BYTES_TO_BITS(sizeof(RakNetTime)+sizeof(unsigned char))+payloadBitLength; } else { memcpy( packet->data, out.GetData()+payloadWriteByteOffset, BITS_TO_BYTES(payloadBitLength) ); packet->bitSize=payloadBitLength; } packet->length=(unsigned int) BITS_TO_BYTES(packet->bitSize); packet->systemAddress.systemIndex=(SystemIndex)-1; packet->systemAddress=originalSender; return RR_CONTINUE_PROCESSING; } // Absorb return RR_STOP_PROCESSING_AND_DEALLOCATE; } return RR_CONTINUE_PROCESSING; }
int WRAPI WRWriteBitmapToData( HBITMAP hbitmap, BYTE **data, uint_32 *size ) { BITMAPFILEHEADER bmfh; BITMAPINFO *bmi; long bitmap_size; long number_of_bytes; HDC hdc; if( hbitmap == (HBITMAP)NULL || data == NULL || size == NULL ) { return( FALSE ); } bmi = WRGetDIBitmapInfo( hbitmap ); if( bmi == NULL ) { return( FALSE ); } number_of_bytes = BITS_TO_BYTES( bmi->bmiHeader.biBitCount * bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight ); bitmap_size = DIB_INFO_SIZE( bmi->bmiHeader.biBitCount ); hdc = GetDC( (HWND)NULL ); GetDIBits( hdc, hbitmap, 0, bmi->bmiHeader.biHeight, NULL, bmi, DIB_RGB_COLORS ); ReleaseDC( (HWND)NULL, hdc ); if( bmi->bmiHeader.biSizeImage == 0 ) { bmi->bmiHeader.biSizeImage = number_of_bytes; } else { number_of_bytes = bmi->bmiHeader.biSizeImage; } bmfh.bfType = BITMAP_TYPE; bmfh.bfSize = sizeof( BITMAPFILEHEADER ) + bitmap_size + number_of_bytes; bmfh.bfReserved1 = 0; bmfh.bfReserved2 = 0; bmfh.bfOffBits = sizeof( BITMAPFILEHEADER ) + bitmap_size; // make sure the bitmap can actually be malloc'd!! if( bmfh.bfSize > INT_MAX ) { MemFree( bmi ); return( FALSE ); } *data = MemAlloc( bmfh.bfSize ); if( *data == NULL ) { MemFree( bmi ); return( FALSE ); } *size = 0; memcpy( *data + *size, &bmfh, sizeof( BITMAPFILEHEADER ) ); *size += sizeof( BITMAPFILEHEADER ); memcpy( *data + *size, bmi, bitmap_size ); *size += bitmap_size; if( !WRWriteDataInPiecesData( bmi, data, size, hbitmap ) ) { MemFree( bmi ); return( FALSE ); } MemFree( bmi ); return( TRUE ); }
/*@ +charint @*/ bool ais_binary_decode(const struct gpsd_errout_t *errout, struct ais_t *ais, const unsigned char *bits, size_t bitlen, struct ais_type24_queue_t *type24_queue) /* decode an AIS binary packet */ { unsigned int u; int i; #ifdef S_SPLINT_S assert(type24_queue != NULL); #endif /* S_SPLINT_S */ #define UBITS(s, l) ubits((unsigned char *)bits, s, l, false) #define SBITS(s, l) sbits((signed char *)bits, s, l, false) #define UCHARS(s, to) from_sixbit((unsigned char *)bits, s, sizeof(to)-1, to) #define ENDCHARS(s, to) from_sixbit((unsigned char *)bits, s, (bitlen-(s))/6,to) ais->type = UBITS(0, 6); ais->repeat = UBITS(6, 2); ais->mmsi = UBITS(8, 30); gpsd_log(errout, LOG_INF, "AIVDM message type %d, MMSI %09d:\n", ais->type, ais->mmsi); #define PERMISSIVE_LENGTH_CHECK(correct) \ if (bitlen < correct) { \ gpsd_log(errout, LOG_ERROR, \ "AIVDM message type %d size < %d bits (%zd).\n", \ ais->type, correct, bitlen); \ return false; \ } else if (bitlen > correct) { \ gpsd_log(errout, LOG_WARN, \ "AIVDM message type %d size > %d bits (%zd).\n", \ ais->type, correct, bitlen); \ } #define RANGE_CHECK(min, max) \ if (bitlen < min || bitlen > max) { \ gpsd_log(errout, LOG_ERROR, \ "AIVDM message type %d size is out of range (%zd).\n", \ ais->type, bitlen); \ return false; \ } /* * Something about the shape of this switch statement confuses * GNU indent so badly that there is no point in trying to be * finer-grained than leaving it all alone. */ /* *INDENT-OFF* */ switch (ais->type) { case 1: /* Position Report */ case 2: case 3: PERMISSIVE_LENGTH_CHECK(168) ais->type1.status = UBITS(38, 4); ais->type1.turn = SBITS(42, 8); ais->type1.speed = UBITS(50, 10); ais->type1.accuracy = UBITS(60, 1)!=0; ais->type1.lon = SBITS(61, 28); ais->type1.lat = SBITS(89, 27); ais->type1.course = UBITS(116, 12); ais->type1.heading = UBITS(128, 9); ais->type1.second = UBITS(137, 6); ais->type1.maneuver = UBITS(143, 2); //ais->type1.spare = UBITS(145, 3); ais->type1.raim = UBITS(148, 1)!=0; ais->type1.radio = UBITS(149, 19); break; case 4: /* Base Station Report */ case 11: /* UTC/Date Response */ PERMISSIVE_LENGTH_CHECK(168) ais->type4.year = UBITS(38, 14); ais->type4.month = UBITS(52, 4); ais->type4.day = UBITS(56, 5); ais->type4.hour = UBITS(61, 5); ais->type4.minute = UBITS(66, 6); ais->type4.second = UBITS(72, 6); ais->type4.accuracy = UBITS(78, 1)!=0; ais->type4.lon = SBITS(79, 28); ais->type4.lat = SBITS(107, 27); ais->type4.epfd = UBITS(134, 4); //ais->type4.spare = UBITS(138, 10); ais->type4.raim = UBITS(148, 1)!=0; ais->type4.radio = UBITS(149, 19); break; case 5: /* Ship static and voyage related data */ if (bitlen != 424) { gpsd_log(errout, LOG_WARN, "AIVDM message type 5 size not 424 bits (%zd).\n", bitlen); /* * For unknown reasons, a lot of transmitters in the wild ship * with a length of 420 or 422. This is a recoverable error. */ if (bitlen < 420) return false; } ais->type5.ais_version = UBITS(38, 2); ais->type5.imo = UBITS(40, 30); UCHARS(70, ais->type5.callsign); UCHARS(112, ais->type5.shipname); ais->type5.shiptype = UBITS(232, 8); ais->type5.to_bow = UBITS(240, 9); ais->type5.to_stern = UBITS(249, 9); ais->type5.to_port = UBITS(258, 6); ais->type5.to_starboard = UBITS(264, 6); ais->type5.epfd = UBITS(270, 4); ais->type5.month = UBITS(274, 4); ais->type5.day = UBITS(278, 5); ais->type5.hour = UBITS(283, 5); ais->type5.minute = UBITS(288, 6); ais->type5.draught = UBITS(294, 8); UCHARS(302, ais->type5.destination); if (bitlen >= 423) ais->type5.dte = UBITS(422, 1); //ais->type5.spare = UBITS(423, 1); break; case 6: /* Addressed Binary Message */ RANGE_CHECK(88, 1008); ais->type6.seqno = UBITS(38, 2); ais->type6.dest_mmsi = UBITS(40, 30); ais->type6.retransmit = UBITS(70, 1)!=0; //ais->type6.spare = UBITS(71, 1); ais->type6.dac = UBITS(72, 10); ais->type6.fid = UBITS(82, 6); ais->type6.bitcount = bitlen - 88; /* not strictly required - helps stability in testing */ (void)memset(ais->type6.bitdata, '\0', sizeof(ais->type6.bitdata)); ais->type6.structured = false; /* Inland AIS */ if (ais->type6.dac == 200) { switch (ais->type6.fid) { case 21: /* ETA at lock/bridge/terminal */ if (bitlen != 248) break; UCHARS(88, ais->type6.dac200fid21.country); UCHARS(100, ais->type6.dac200fid21.locode); UCHARS(118, ais->type6.dac200fid21.section); UCHARS(148, ais->type6.dac200fid21.terminal); UCHARS(178, ais->type6.dac200fid21.hectometre); ais->type6.dac200fid21.month = UBITS(208, 4); ais->type6.dac200fid21.day = UBITS(212, 5); ais->type6.dac200fid21.hour = UBITS(217, 5); ais->type6.dac200fid21.minute = UBITS(222, 6); ais->type6.dac200fid21.tugs = UBITS(228, 3); ais->type6.dac200fid21.airdraught = UBITS(231, 12); /* skip 5 bits */ ais->type6.structured = true; break; case 22: /* RTA at lock/bridge/terminal */ if (bitlen != 232) break; UCHARS(88, ais->type6.dac200fid22.country); UCHARS(100, ais->type6.dac200fid22.locode); UCHARS(118, ais->type6.dac200fid22.section); UCHARS(148, ais->type6.dac200fid22.terminal); UCHARS(178, ais->type6.dac200fid22.hectometre); ais->type6.dac200fid22.month = UBITS(208, 4); ais->type6.dac200fid22.day = UBITS(212, 5); ais->type6.dac200fid22.hour = UBITS(217, 5); ais->type6.dac200fid22.minute = UBITS(222, 6); ais->type6.dac200fid22.status = UBITS(228, 2); /* skip 2 bits */ ais->type6.structured = true; break; case 55: /* Number of Persons On Board */ if (bitlen != 168) break; ais->type6.dac200fid55.crew = UBITS(88, 8); ais->type6.dac200fid55.passengers = UBITS(96, 13); ais->type6.dac200fid55.personnel = UBITS(109, 8); /* skip 51 bits */ ais->type6.structured = true; break; } break; } /* UK and Republic Of Ireland */ else if (ais->type6.dac == 235 || ais->type6.dac == 250) { switch (ais->type6.fid) { case 10: /* GLA - AtoN monitoring data */ if (bitlen != 136) break; ais->type6.dac235fid10.ana_int = UBITS(88, 10); ais->type6.dac235fid10.ana_ext1 = UBITS(98, 10); ais->type6.dac235fid10.ana_ext2 = UBITS(108, 10); ais->type6.dac235fid10.racon = UBITS(118, 2); ais->type6.dac235fid10.light = UBITS(120, 2); ais->type6.dac235fid10.alarm = UBITS(122, 1); ais->type6.dac235fid10.stat_ext = UBITS(123, 8); ais->type6.dac235fid10.off_pos = UBITS(131, 1); /* skip 4 bits */ ais->type6.structured = true; break; } break; } /* International */ else if (ais->type6.dac == 1) switch (ais->type6.fid) { case 12: /* IMO236 - Dangerous cargo indication */ UCHARS(88, ais->type6.dac1fid12.lastport); ais->type6.dac1fid12.lmonth = UBITS(118, 4); ais->type6.dac1fid12.lday = UBITS(122, 5); ais->type6.dac1fid12.lhour = UBITS(127, 5); ais->type6.dac1fid12.lminute = UBITS(132, 6); UCHARS(138, ais->type6.dac1fid12.nextport); ais->type6.dac1fid12.nmonth = UBITS(168, 4); ais->type6.dac1fid12.nday = UBITS(172, 5); ais->type6.dac1fid12.nhour = UBITS(177, 5); ais->type6.dac1fid12.nminute = UBITS(182, 6); UCHARS(188, ais->type6.dac1fid12.dangerous); UCHARS(308, ais->type6.dac1fid12.imdcat); ais->type6.dac1fid12.unid = UBITS(332, 13); ais->type6.dac1fid12.amount = UBITS(345, 10); ais->type6.dac1fid12.unit = UBITS(355, 2); /* skip 3 bits */ ais->type6.structured = true; break; case 14: /* IMO236 - Tidal Window */ ais->type6.dac1fid32.month = UBITS(88, 4); ais->type6.dac1fid32.day = UBITS(92, 5); #define ARRAY_BASE 97 #define ELEMENT_SIZE 93 for (u = 0; ARRAY_BASE + (ELEMENT_SIZE*u) <= bitlen; u++) { int a = ARRAY_BASE + (ELEMENT_SIZE*u); struct tidal_t *tp = &ais->type6.dac1fid32.tidals[u]; tp->lat = SBITS(a + 0, 27); tp->lon = SBITS(a + 27, 28); tp->from_hour = UBITS(a + 55, 5); tp->from_min = UBITS(a + 60, 6); tp->to_hour = UBITS(a + 66, 5); tp->to_min = UBITS(a + 71, 6); tp->cdir = UBITS(a + 77, 9); tp->cspeed = UBITS(a + 86, 7); } ais->type6.dac1fid32.ntidals = u; #undef ARRAY_BASE #undef ELEMENT_SIZE ais->type6.structured = true; break; case 15: /* IMO236 - Extended Ship Static and Voyage Related Data */ ais->type6.dac1fid15.airdraught = UBITS(56, 11); ais->type6.structured = true; break; case 16: /* IMO236 - Number of persons on board */ if (ais->type6.bitcount == 136) ais->type6.dac1fid16.persons = UBITS(88, 13);/* 289 */ else ais->type6.dac1fid16.persons = UBITS(55, 13);/* 236 */ ais->type6.structured = true; break; case 18: /* IMO289 - Clearance time to enter port */ ais->type6.dac1fid18.linkage = UBITS(88, 10); ais->type6.dac1fid18.month = UBITS(98, 4); ais->type6.dac1fid18.day = UBITS(102, 5); ais->type6.dac1fid18.hour = UBITS(107, 5); ais->type6.dac1fid18.minute = UBITS(112, 6); UCHARS(118, ais->type6.dac1fid18.portname); UCHARS(238, ais->type6.dac1fid18.destination); ais->type6.dac1fid18.lon = SBITS(268, 25); ais->type6.dac1fid18.lat = SBITS(293, 24); /* skip 43 bits */ ais->type6.structured = true; break; case 20: /* IMO289 - Berthing data - addressed */ ais->type6.dac1fid20.linkage = UBITS(88, 10); ais->type6.dac1fid20.berth_length = UBITS(98, 9); ais->type6.dac1fid20.berth_depth = UBITS(107, 8); ais->type6.dac1fid20.position = UBITS(115, 3); ais->type6.dac1fid20.month = UBITS(118, 4); ais->type6.dac1fid20.day = UBITS(122, 5); ais->type6.dac1fid20.hour = UBITS(127, 5); ais->type6.dac1fid20.minute = UBITS(132, 6); ais->type6.dac1fid20.availability = UBITS(138, 1); ais->type6.dac1fid20.agent = UBITS(139, 2); ais->type6.dac1fid20.fuel = UBITS(141, 2); ais->type6.dac1fid20.chandler = UBITS(143, 2); ais->type6.dac1fid20.stevedore = UBITS(145, 2); ais->type6.dac1fid20.electrical = UBITS(147, 2); ais->type6.dac1fid20.water = UBITS(149, 2); ais->type6.dac1fid20.customs = UBITS(151, 2); ais->type6.dac1fid20.cartage = UBITS(153, 2); ais->type6.dac1fid20.crane = UBITS(155, 2); ais->type6.dac1fid20.lift = UBITS(157, 2); ais->type6.dac1fid20.medical = UBITS(159, 2); ais->type6.dac1fid20.navrepair = UBITS(161, 2); ais->type6.dac1fid20.provisions = UBITS(163, 2); ais->type6.dac1fid20.shiprepair = UBITS(165, 2); ais->type6.dac1fid20.surveyor = UBITS(167, 2); ais->type6.dac1fid20.steam = UBITS(169, 2); ais->type6.dac1fid20.tugs = UBITS(171, 2); ais->type6.dac1fid20.solidwaste = UBITS(173, 2); ais->type6.dac1fid20.liquidwaste = UBITS(175, 2); ais->type6.dac1fid20.hazardouswaste = UBITS(177, 2); ais->type6.dac1fid20.ballast = UBITS(179, 2); ais->type6.dac1fid20.additional = UBITS(181, 2); ais->type6.dac1fid20.regional1 = UBITS(183, 2); ais->type6.dac1fid20.regional2 = UBITS(185, 2); ais->type6.dac1fid20.future1 = UBITS(187, 2); ais->type6.dac1fid20.future2 = UBITS(189, 2); UCHARS(191, ais->type6.dac1fid20.berth_name); ais->type6.dac1fid20.berth_lon = SBITS(311, 25); ais->type6.dac1fid20.berth_lat = SBITS(336, 24); ais->type6.structured = true; break; case 23: /* IMO289 - Area notice - addressed */ break; case 25: /* IMO289 - Dangerous cargo indication */ ais->type6.dac1fid25.unit = UBITS(88, 2); ais->type6.dac1fid25.amount = UBITS(90, 10); for (u = 0; 100 + u*17 < bitlen; u++) { ais->type6.dac1fid25.cargos[u].code = UBITS(100+u*17,4); ais->type6.dac1fid25.cargos[u].subtype = UBITS(104+u*17,13); } ais->type6.dac1fid25.ncargos = u; ais->type6.structured = true; break; case 28: /* IMO289 - Route info - addressed */ ais->type6.dac1fid28.linkage = UBITS(88, 10); ais->type6.dac1fid28.sender = UBITS(98, 3); ais->type6.dac1fid28.rtype = UBITS(101, 5); ais->type6.dac1fid28.month = UBITS(106, 4); ais->type6.dac1fid28.day = UBITS(110, 5); ais->type6.dac1fid28.hour = UBITS(115, 5); ais->type6.dac1fid28.minute = UBITS(120, 6); ais->type6.dac1fid28.duration = UBITS(126, 18); ais->type6.dac1fid28.waycount = UBITS(144, 5); #define ARRAY_BASE 149 #define ELEMENT_SIZE 55 for (u = 0; u < (unsigned char)ais->type6.dac1fid28.waycount; u++) { int a = ARRAY_BASE + (ELEMENT_SIZE*u); ais->type6.dac1fid28.waypoints[u].lon = SBITS(a+0, 28); ais->type6.dac1fid28.waypoints[u].lat = SBITS(a+28,27); } #undef ARRAY_BASE #undef ELEMENT_SIZE ais->type6.structured = true; break; case 30: /* IMO289 - Text description - addressed */ ais->type6.dac1fid30.linkage = UBITS(88, 10); ENDCHARS(98, ais->type6.dac1fid30.text); ais->type6.structured = true; break; case 32: /* IMO289 - Tidal Window */ ais->type6.dac1fid32.month = UBITS(88, 4); ais->type6.dac1fid32.day = UBITS(92, 5); #define ARRAY_BASE 97 #define ELEMENT_SIZE 88 for (u = 0; ARRAY_BASE + (ELEMENT_SIZE*u) <= bitlen; u++) { int a = ARRAY_BASE + (ELEMENT_SIZE*u); struct tidal_t *tp = &ais->type6.dac1fid32.tidals[u]; tp->lon = SBITS(a + 0, 25); tp->lat = SBITS(a + 25, 24); tp->from_hour = UBITS(a + 49, 5); tp->from_min = UBITS(a + 54, 6); tp->to_hour = UBITS(a + 60, 5); tp->to_min = UBITS(a + 65, 6); tp->cdir = UBITS(a + 71, 9); tp->cspeed = UBITS(a + 80, 8); } ais->type6.dac1fid32.ntidals = u; #undef ARRAY_BASE #undef ELEMENT_SIZE ais->type6.structured = true; break; } if (!ais->type6.structured) (void)memcpy(ais->type6.bitdata, (char *)bits + (88 / CHAR_BIT), BITS_TO_BYTES(ais->type6.bitcount)); break; case 7: /* Binary acknowledge */ case 13: /* Safety Related Acknowledge */ { unsigned int mmsi[4]; RANGE_CHECK(72, 158); for (u = 0; u < sizeof(mmsi)/sizeof(mmsi[0]); u++) if (bitlen > 40 + 32*u) mmsi[u] = UBITS(40 + 32*u, 30); else mmsi[u] = 0; /*@ -usedef @*/ ais->type7.mmsi1 = mmsi[0]; ais->type7.mmsi2 = mmsi[1]; ais->type7.mmsi3 = mmsi[2]; ais->type7.mmsi4 = mmsi[3]; /*@ +usedef @*/ break; } case 8: /* Binary Broadcast Message */ RANGE_CHECK(56, 1008); //ais->type8.spare = UBITS(38, 2); ais->type8.dac = UBITS(40, 10); ais->type8.fid = UBITS(50, 6); ais->type8.bitcount = bitlen - 56; /* not strictly required - helps stability in testing */ (void)memset(ais->type8.bitdata, '\0', sizeof(ais->type8.bitdata)); ais->type8.structured = false; if (ais->type8.dac == 1) switch (ais->type8.fid) { case 11: /* IMO236 - Meteorological/Hydrological data */ /* layout is almost identical to FID=31 from IMO289 */ ais->type8.dac1fid11.lat = SBITS(56, 24); ais->type8.dac1fid11.lon = SBITS(80, 25); ais->type8.dac1fid11.day = UBITS(105, 5); ais->type8.dac1fid11.hour = UBITS(110, 5); ais->type8.dac1fid11.minute = UBITS(115, 6); ais->type8.dac1fid11.wspeed = UBITS(121, 7); ais->type8.dac1fid11.wgust = UBITS(128, 7); ais->type8.dac1fid11.wdir = UBITS(135, 9); ais->type8.dac1fid11.wgustdir = UBITS(144, 9); ais->type8.dac1fid11.airtemp = UBITS(153, 11); ais->type8.dac1fid11.humidity = UBITS(164, 7); ais->type8.dac1fid11.dewpoint = UBITS(171, 10); ais->type8.dac1fid11.pressure = UBITS(181, 9); ais->type8.dac1fid11.pressuretend = UBITS(190, 2); ais->type8.dac1fid11.visibility = UBITS(192, 8); ais->type8.dac1fid11.waterlevel = UBITS(200, 9); ais->type8.dac1fid11.leveltrend = UBITS(209, 2); ais->type8.dac1fid11.cspeed = UBITS(211, 8); ais->type8.dac1fid11.cdir = UBITS(219, 9); ais->type8.dac1fid11.cspeed2 = UBITS(228, 8); ais->type8.dac1fid11.cdir2 = UBITS(236, 9); ais->type8.dac1fid11.cdepth2 = UBITS(245, 5); ais->type8.dac1fid11.cspeed3 = UBITS(250, 8); ais->type8.dac1fid11.cdir3 = UBITS(258, 9); ais->type8.dac1fid11.cdepth3 = UBITS(267, 5); ais->type8.dac1fid11.waveheight = UBITS(272, 8); ais->type8.dac1fid11.waveperiod = UBITS(280, 6); ais->type8.dac1fid11.wavedir = UBITS(286, 9); ais->type8.dac1fid11.swellheight = UBITS(295, 8); ais->type8.dac1fid11.swellperiod = UBITS(303, 6); ais->type8.dac1fid11.swelldir = UBITS(309, 9); ais->type8.dac1fid11.seastate = UBITS(318, 4); ais->type8.dac1fid11.watertemp = UBITS(322, 10); ais->type8.dac1fid11.preciptype = UBITS(332, 3); ais->type8.dac1fid11.salinity = UBITS(335, 9); ais->type8.dac1fid11.ice = UBITS(344, 2); ais->type8.structured = true; break; case 13: /* IMO236 - Fairway closed */ UCHARS(56, ais->type8.dac1fid13.reason); UCHARS(176, ais->type8.dac1fid13.closefrom); UCHARS(296, ais->type8.dac1fid13.closeto); ais->type8.dac1fid13.radius = UBITS(416, 10); ais->type8.dac1fid13.extunit = UBITS(426, 2); ais->type8.dac1fid13.fday = UBITS(428, 5); ais->type8.dac1fid13.fmonth = UBITS(433, 4); ais->type8.dac1fid13.fhour = UBITS(437, 5); ais->type8.dac1fid13.fminute = UBITS(442, 6); ais->type8.dac1fid13.tday = UBITS(448, 5); ais->type8.dac1fid13.tmonth = UBITS(453, 4); ais->type8.dac1fid13.thour = UBITS(457, 5); ais->type8.dac1fid13.tminute = UBITS(462, 6); /* skip 4 bits */ ais->type8.structured = true; break; case 15: /* IMO236 - Extended ship and voyage */ ais->type8.dac1fid15.airdraught = UBITS(56, 11); /* skip 5 bits */ ais->type8.structured = true; break; case 16: /* Number of Persons On Board */ if (ais->type8.bitcount == 136) ais->type8.dac1fid16.persons = UBITS(88, 13);/* 289 */ else ais->type8.dac1fid16.persons = UBITS(55, 13);/* 236 */ ais->type8.structured = true; break; case 17: /* IMO289 - VTS-generated/synthetic targets */ #define ARRAY_BASE 56 #define ELEMENT_SIZE 122 for (u = 0; ARRAY_BASE + (ELEMENT_SIZE*u) <= bitlen; u++) { struct target_t *tp = &ais->type8.dac1fid17.targets[u]; int a = ARRAY_BASE + (ELEMENT_SIZE*u); tp->idtype = UBITS(a + 0, 2); switch (tp->idtype) { case DAC1FID17_IDTYPE_MMSI: tp->id.mmsi = UBITS(a + 2, 42); break; case DAC1FID17_IDTYPE_IMO: tp->id.imo = UBITS(a + 2, 42); break; case DAC1FID17_IDTYPE_CALLSIGN: UCHARS(a+2, tp->id.callsign); break; default: UCHARS(a+2, tp->id.other); break; } /* skip 4 bits */ tp->lat = SBITS(a + 48, 24); tp->lon = SBITS(a + 72, 25); tp->course = UBITS(a + 97, 9); tp->second = UBITS(a + 106, 6); tp->speed = UBITS(a + 112, 10); } ais->type8.dac1fid17.ntargets = u; #undef ARRAY_BASE #undef ELEMENT_SIZE ais->type8.structured = true; break; case 19: /* IMO289 - Marine Traffic Signal */ ais->type8.dac1fid19.linkage = UBITS(56, 10); UCHARS(66, ais->type8.dac1fid19.station); ais->type8.dac1fid19.lon = SBITS(186, 25); ais->type8.dac1fid19.lat = SBITS(211, 24); ais->type8.dac1fid19.status = UBITS(235, 2); ais->type8.dac1fid19.signal = UBITS(237, 5); ais->type8.dac1fid19.hour = UBITS(242, 5); ais->type8.dac1fid19.minute = UBITS(247, 6); ais->type8.dac1fid19.nextsignal = UBITS(253, 5); /* skip 102 bits */ ais->type8.structured = true; break; case 21: /* IMO289 - Weather obs. report from ship */ break; case 22: /* IMO289 - Area notice - broadcast */ break; case 24: /* IMO289 - Extended ship static & voyage-related data */ break; case 26: /* IMO289 - Environmental */ break; case 27: /* IMO289 - Route information - broadcast */ ais->type8.dac1fid27.linkage = UBITS(56, 10); ais->type8.dac1fid27.sender = UBITS(66, 3); ais->type8.dac1fid27.rtype = UBITS(69, 5); ais->type8.dac1fid27.month = UBITS(74, 4); ais->type8.dac1fid27.day = UBITS(78, 5); ais->type8.dac1fid27.hour = UBITS(83, 5); ais->type8.dac1fid27.minute = UBITS(88, 6); ais->type8.dac1fid27.duration = UBITS(94, 18); ais->type8.dac1fid27.waycount = UBITS(112, 5); #define ARRAY_BASE 117 #define ELEMENT_SIZE 55 for (i = 0; i < ais->type8.dac1fid27.waycount; i++) { int a = ARRAY_BASE + (ELEMENT_SIZE*i); ais->type8.dac1fid27.waypoints[i].lon = SBITS(a + 0, 28); ais->type8.dac1fid27.waypoints[i].lat = SBITS(a + 28, 27); } #undef ARRAY_BASE #undef ELEMENT_SIZE ais->type8.structured = true; break; case 29: /* IMO289 - Text Description - broadcast */ ais->type8.dac1fid29.linkage = UBITS(56, 10); ENDCHARS(66, ais->type8.dac1fid29.text); ais->type8.structured = true; break; case 31: /* IMO289 - Meteorological/Hydrological data */ ais->type8.dac1fid31.lon = SBITS(56, 25); ais->type8.dac1fid31.lat = SBITS(81, 24); ais->type8.dac1fid31.accuracy = (bool)UBITS(105, 1); ais->type8.dac1fid31.day = UBITS(106, 5); ais->type8.dac1fid31.hour = UBITS(111, 5); ais->type8.dac1fid31.minute = UBITS(116, 6); ais->type8.dac1fid31.wspeed = UBITS(122, 7); ais->type8.dac1fid31.wgust = UBITS(129, 7); ais->type8.dac1fid31.wdir = UBITS(136, 9); ais->type8.dac1fid31.wgustdir = UBITS(145, 9); ais->type8.dac1fid31.airtemp = SBITS(154, 11); ais->type8.dac1fid31.humidity = UBITS(165, 7); ais->type8.dac1fid31.dewpoint = SBITS(172, 10); ais->type8.dac1fid31.pressure = UBITS(182, 9); ais->type8.dac1fid31.pressuretend = UBITS(191, 2); ais->type8.dac1fid31.visgreater = UBITS(193, 1); ais->type8.dac1fid31.visibility = UBITS(194, 7); ais->type8.dac1fid31.waterlevel = UBITS(201, 12); ais->type8.dac1fid31.leveltrend = UBITS(213, 2); ais->type8.dac1fid31.cspeed = UBITS(215, 8); ais->type8.dac1fid31.cdir = UBITS(223, 9); ais->type8.dac1fid31.cspeed2 = UBITS(232, 8); ais->type8.dac1fid31.cdir2 = UBITS(240, 9); ais->type8.dac1fid31.cdepth2 = UBITS(249, 5); ais->type8.dac1fid31.cspeed3 = UBITS(254, 8); ais->type8.dac1fid31.cdir3 = UBITS(262, 9); ais->type8.dac1fid31.cdepth3 = UBITS(271, 5); ais->type8.dac1fid31.waveheight = UBITS(276, 8); ais->type8.dac1fid31.waveperiod = UBITS(284, 6); ais->type8.dac1fid31.wavedir = UBITS(290, 9); ais->type8.dac1fid31.swellheight = UBITS(299, 8); ais->type8.dac1fid31.swellperiod = UBITS(307, 6); ais->type8.dac1fid31.swelldir = UBITS(313, 9); ais->type8.dac1fid31.seastate = UBITS(322, 4); ais->type8.dac1fid31.watertemp = SBITS(326, 10); ais->type8.dac1fid31.preciptype = UBITS(336, 3); ais->type8.dac1fid31.salinity = UBITS(339, 9); ais->type8.dac1fid31.ice = UBITS(348, 2); ais->type8.structured = true; break; } else if (ais->type8.dac == 200) { switch (ais->type8.fid) { case 10: /* Inland ship static and voyage related data */ if (bitlen != 168) break; UCHARS(56, ais->type8.dac200fid10.vin); ais->type8.dac200fid10.length = UBITS(104, 13); ais->type8.dac200fid10.beam = UBITS(117, 10); ais->type8.dac200fid10.shiptype = UBITS(127, 14); ais->type8.dac200fid10.hazard = UBITS(141, 3); ais->type8.dac200fid10.draught = UBITS(144, 11); ais->type8.dac200fid10.loaded = UBITS(155, 2); ais->type8.dac200fid10.speed_q = (bool)UBITS(157, 1); ais->type8.dac200fid10.course_q = (bool)UBITS(158, 1); ais->type8.dac200fid10.heading_q = (bool)UBITS(159, 1); /* skip 8 bits */ /* * Attempt to prevent false matches with this message type * by range-checking certain fields. */ if (ais->type8.dac200fid10.hazard > DAC200FID10_HAZARD_MAX || !isascii((int)ais->type8.dac200fid10.vin[0])) ais->type8.structured = false; else ais->type8.structured = true; break; case 23: /* EMMA warning */ if (bitlen != 256) break; ais->type8.dac200fid23.start_year = UBITS(56, 8); ais->type8.dac200fid23.start_month = UBITS(64, 4); ais->type8.dac200fid23.start_day = UBITS(68, 5); ais->type8.dac200fid23.end_year = UBITS(73, 8); ais->type8.dac200fid23.end_month = UBITS(81, 4); ais->type8.dac200fid23.end_day = UBITS(85, 5); ais->type8.dac200fid23.start_hour = UBITS(90, 5); ais->type8.dac200fid23.start_minute = UBITS(95, 6); ais->type8.dac200fid23.end_hour = UBITS(101, 5); ais->type8.dac200fid23.end_minute = UBITS(106, 6); ais->type8.dac200fid23.start_lon = SBITS(112, 28); ais->type8.dac200fid23.start_lat = SBITS(140, 27); ais->type8.dac200fid23.end_lon = SBITS(167, 28); ais->type8.dac200fid23.end_lat = SBITS(195, 27); ais->type8.dac200fid23.type = UBITS(222, 4); ais->type8.dac200fid23.min = SBITS(226, 9); ais->type8.dac200fid23.max = SBITS(235, 9); ais->type8.dac200fid23.intensity = UBITS(244, 2); ais->type8.dac200fid23.wind = UBITS(246, 4); /* skip 6 bits */ ais->type8.structured = true; break; case 24: /* Water level */ if (bitlen != 168) break; UCHARS(56, ais->type8.dac200fid24.country); #define ARRAY_BASE 68 #define ELEMENT_SIZE 25 for (i = 0; ARRAY_BASE + (ELEMENT_SIZE*i) < (int)bitlen; i++) { int a = ARRAY_BASE + (ELEMENT_SIZE*i); ais->type8.dac200fid24.gauges[i].id = UBITS(a+0, 11); ais->type8.dac200fid24.gauges[i].level = SBITS(a+11, 14); } ais->type8.dac200fid24.ngauges = i; #undef ARRAY_BASE #undef ELEMENT_SIZE /* skip 6 bits */ ais->type8.structured = true; break; case 40: /* Signal status */ if (bitlen != 168) break; ais->type8.dac200fid40.lon = SBITS(56, 28); ais->type8.dac200fid40.lat = SBITS(84, 27); ais->type8.dac200fid40.form = UBITS(111, 4); ais->type8.dac200fid40.facing = UBITS(115, 9); ais->type8.dac200fid40.direction = UBITS(124, 3); ais->type8.dac200fid40.status = UBITS(127, 30); /* skip 11 bits */ ais->type8.structured = true; break; } } /* land here if we failed to match a known DAC/FID */ if (!ais->type8.structured) (void)memcpy(ais->type8.bitdata, (char *)bits + (56 / CHAR_BIT), BITS_TO_BYTES(ais->type8.bitcount)); break; case 9: /* Standard SAR Aircraft Position Report */ PERMISSIVE_LENGTH_CHECK(168); ais->type9.alt = UBITS(38, 12); ais->type9.speed = UBITS(50, 10); ais->type9.accuracy = (bool)UBITS(60, 1); ais->type9.lon = SBITS(61, 28); ais->type9.lat = SBITS(89, 27); ais->type9.course = UBITS(116, 12); ais->type9.second = UBITS(128, 6); ais->type9.regional = UBITS(134, 8); ais->type9.dte = UBITS(142, 1); //ais->type9.spare = UBITS(143, 3); ais->type9.assigned = UBITS(146, 1)!=0; ais->type9.raim = UBITS(147, 1)!=0; ais->type9.radio = UBITS(148, 20); break; case 10: /* UTC/Date inquiry */ PERMISSIVE_LENGTH_CHECK(72); //ais->type10.spare = UBITS(38, 2); ais->type10.dest_mmsi = UBITS(40, 30); //ais->type10.spare2 = UBITS(70, 2); break; case 12: /* Safety Related Message */ RANGE_CHECK(72, 1008); ais->type12.seqno = UBITS(38, 2); ais->type12.dest_mmsi = UBITS(40, 30); ais->type12.retransmit = (bool)UBITS(70, 1); //ais->type12.spare = UBITS(71, 1); ENDCHARS(72, ais->type12.text); break; case 14: /* Safety Related Broadcast Message */ RANGE_CHECK(40, 1008); //ais->type14.spare = UBITS(38, 2); ENDCHARS(40, ais->type14.text); break; case 15: /* Interrogation */ RANGE_CHECK(88, 168); (void)memset(&ais->type15, '\0', sizeof(ais->type15)); //ais->type14.spare = UBITS(38, 2); ais->type15.mmsi1 = UBITS(40, 30); ais->type15.type1_1 = UBITS(70, 6); ais->type15.type1_1 = UBITS(70, 6); ais->type15.offset1_1 = UBITS(76, 12); //ais->type14.spare2 = UBITS(88, 2); if (bitlen > 90) { ais->type15.type1_2 = UBITS(90, 6); ais->type15.offset1_2 = UBITS(96, 12); //ais->type14.spare3 = UBITS(108, 2); if (bitlen > 110) { ais->type15.mmsi2 = UBITS(110, 30); ais->type15.type2_1 = UBITS(140, 6); ais->type15.offset2_1 = UBITS(146, 12); //ais->type14.spare4 = UBITS(158, 2); } } break; case 16: /* Assigned Mode Command */ RANGE_CHECK(96, 144); ais->type16.mmsi1 = UBITS(40, 30); ais->type16.offset1 = UBITS(70, 12); ais->type16.increment1 = UBITS(82, 10); if (bitlen < 144) ais->type16.mmsi2=ais->type16.offset2=ais->type16.increment2 = 0; else { ais->type16.mmsi2 = UBITS(92, 30); ais->type16.offset2 = UBITS(122, 12); ais->type16.increment2 = UBITS(134, 10); } break; case 17: /* GNSS Broadcast Binary Message */ RANGE_CHECK(80, 816); //ais->type17.spare = UBITS(38, 2); ais->type17.lon = UBITS(40, 18); ais->type17.lat = UBITS(58, 17); //ais->type17.spare = UBITS(75, 4); ais->type17.bitcount = bitlen - 80; (void)memcpy(ais->type17.bitdata, (char *)bits + (80 / CHAR_BIT), BITS_TO_BYTES(ais->type17.bitcount)); break; case 18: /* Standard Class B CS Position Report */ PERMISSIVE_LENGTH_CHECK(168) ais->type18.reserved = UBITS(38, 8); ais->type18.speed = UBITS(46, 10); ais->type18.accuracy = UBITS(56, 1)!=0; ais->type18.lon = SBITS(57, 28); ais->type18.lat = SBITS(85, 27); ais->type18.course = UBITS(112, 12); ais->type18.heading = UBITS(124, 9); ais->type18.second = UBITS(133, 6); ais->type18.regional = UBITS(139, 2); ais->type18.cs = UBITS(141, 1)!=0; ais->type18.display = UBITS(142, 1)!=0; ais->type18.dsc = UBITS(143, 1)!=0; ais->type18.band = UBITS(144, 1)!=0; ais->type18.msg22 = UBITS(145, 1)!=0; ais->type18.assigned = UBITS(146, 1)!=0; ais->type18.raim = UBITS(147, 1)!=0; ais->type18.radio = UBITS(148, 20); break; case 19: /* Extended Class B CS Position Report */ PERMISSIVE_LENGTH_CHECK(312) ais->type19.reserved = UBITS(38, 8); ais->type19.speed = UBITS(46, 10); ais->type19.accuracy = UBITS(56, 1)!=0; ais->type19.lon = SBITS(57, 28); ais->type19.lat = SBITS(85, 27); ais->type19.course = UBITS(112, 12); ais->type19.heading = UBITS(124, 9); ais->type19.second = UBITS(133, 6); ais->type19.regional = UBITS(139, 4); UCHARS(143, ais->type19.shipname); ais->type19.shiptype = UBITS(263, 8); ais->type19.to_bow = UBITS(271, 9); ais->type19.to_stern = UBITS(280, 9); ais->type19.to_port = UBITS(289, 6); ais->type19.to_starboard = UBITS(295, 6); ais->type19.epfd = UBITS(301, 4); ais->type19.raim = UBITS(305, 1)!=0; ais->type19.dte = UBITS(306, 1)!=0; ais->type19.assigned = UBITS(307, 1)!=0; //ais->type19.spare = UBITS(308, 4); break; case 20: /* Data Link Management Message */ RANGE_CHECK(72, 160); //ais->type20.spare = UBITS(38, 2); ais->type20.offset1 = UBITS(40, 12); ais->type20.number1 = UBITS(52, 4); ais->type20.timeout1 = UBITS(56, 3); ais->type20.increment1 = UBITS(59, 11); ais->type20.offset2 = UBITS(70, 12); ais->type20.number2 = UBITS(82, 4); ais->type20.timeout2 = UBITS(86, 3); ais->type20.increment2 = UBITS(89, 11); ais->type20.offset3 = UBITS(100, 12); ais->type20.number3 = UBITS(112, 4); ais->type20.timeout3 = UBITS(116, 3); ais->type20.increment3 = UBITS(119, 11); ais->type20.offset4 = UBITS(130, 12); ais->type20.number4 = UBITS(142, 4); ais->type20.timeout4 = UBITS(146, 3); ais->type20.increment4 = UBITS(149, 11); break; case 21: /* Aid-to-Navigation Report */ RANGE_CHECK(272, 360); ais->type21.aid_type = UBITS(38, 5); from_sixbit((unsigned char *)bits, 43, 20, ais->type21.name); ais->type21.accuracy = UBITS(163, 1); ais->type21.lon = SBITS(164, 28); ais->type21.lat = SBITS(192, 27); ais->type21.to_bow = UBITS(219, 9); ais->type21.to_stern = UBITS(228, 9); ais->type21.to_port = UBITS(237, 6); ais->type21.to_starboard = UBITS(243, 6); ais->type21.epfd = UBITS(249, 4); ais->type21.second = UBITS(253, 6); ais->type21.off_position = UBITS(259, 1)!=0; ais->type21.regional = UBITS(260, 8); ais->type21.raim = UBITS(268, 1)!=0; ais->type21.virtual_aid = UBITS(269, 1)!=0; ais->type21.assigned = UBITS(270, 1)!=0; //ais->type21.spare = UBITS(271, 1); if (strlen(ais->type21.name) == 20 && bitlen > 272) ENDCHARS(272, ais->type21.name+20); break; case 22: /* Channel Management */ PERMISSIVE_LENGTH_CHECK(168) ais->type22.channel_a = UBITS(40, 12); ais->type22.channel_b = UBITS(52, 12); ais->type22.txrx = UBITS(64, 4); ais->type22.power = UBITS(68, 1); ais->type22.addressed = UBITS(139, 1); if (!ais->type22.addressed) { ais->type22.area.ne_lon = SBITS(69, 18); ais->type22.area.ne_lat = SBITS(87, 17); ais->type22.area.sw_lon = SBITS(104, 18); ais->type22.area.sw_lat = SBITS(122, 17); } else { ais->type22.mmsi.dest1 = UBITS(69, 30); ais->type22.mmsi.dest2 = UBITS(104, 30); } ais->type22.band_a = UBITS(140, 1); ais->type22.band_b = UBITS(141, 1); ais->type22.zonesize = UBITS(142, 3); break; case 23: /* Group Assignment Command */ PERMISSIVE_LENGTH_CHECK(160) ais->type23.ne_lon = SBITS(40, 18); ais->type23.ne_lat = SBITS(58, 17); ais->type23.sw_lon = SBITS(75, 18); ais->type23.sw_lat = SBITS(93, 17); ais->type23.stationtype = UBITS(110, 4); ais->type23.shiptype = UBITS(114, 8); ais->type23.txrx = UBITS(144, 4); ais->type23.interval = UBITS(146, 4); ais->type23.quiet = UBITS(150, 4); break; case 24: /* Class B CS Static Data Report */ switch (UBITS(38, 2)) { case 0: RANGE_CHECK(160, 168); /* save incoming 24A shipname/MMSI pairs in a circular queue */ { struct ais_type24a_t *saveptr = &type24_queue->ships[type24_queue->index]; gpsd_log(errout, LOG_PROG, "AIVDM: 24A from %09u stashed.\n", ais->mmsi); saveptr->mmsi = ais->mmsi; UCHARS(40, saveptr->shipname); ++type24_queue->index; type24_queue->index %= MAX_TYPE24_INTERLEAVE; } //ais->type24.a.spare = UBITS(160, 8); UCHARS(40, ais->type24.shipname); ais->type24.part = part_a; return true; case 1: PERMISSIVE_LENGTH_CHECK(168) ais->type24.shiptype = UBITS(40, 8); /* * In ITU-R 1371-4, there are new model and serial fields * carved out of the right-hand end of vendorid, which is * reduced from 7 chars to 3. To cope with older AIS * implementations conforming to revision 3 and older, * unpack the trailing bits *both* ways; truly * revision-4-conformant implementations will have up to * four characters of trailing garbage on the vendorid, * and older implementations will have garbafe in the * model and serial fields. */ UCHARS(48, ais->type24.vendorid); ais->type24.model = UBITS(66, 4); ais->type24.serial = UBITS(70, 20); UCHARS(90, ais->type24.callsign); if (AIS_AUXILIARY_MMSI(ais->mmsi)) { ais->type24.mothership_mmsi = UBITS(132, 30); } else { ais->type24.dim.to_bow = UBITS(132, 9); ais->type24.dim.to_stern = UBITS(141, 9); ais->type24.dim.to_port = UBITS(150, 6); ais->type24.dim.to_starboard = UBITS(156, 6); } //ais->type24.b.spare = UBITS(162, 8); /* search the 24A queue for a matching MMSI */ for (i = 0; i < MAX_TYPE24_INTERLEAVE; i++) { if (type24_queue->ships[i].mmsi == ais->mmsi) { (void)strlcpy(ais->type24.shipname, type24_queue->ships[i].shipname, sizeof(ais->type24.shipname)); gpsd_log(errout, LOG_PROG, "AIVDM 24B from %09u matches a 24A.\n", ais->mmsi); /* prevent false match if a 24B is repeated */ type24_queue->ships[i].mmsi = 0; ais->type24.part = both; return true; } } /* no match, return Part B */ ais->type24.part = part_b; return true; default: gpsd_log(errout, LOG_WARN, "AIVDM message type 24 of subtype unknown.\n"); return false; } // break; case 25: /* Binary Message, Single Slot */ /* this check and the following one reject line noise */ if (bitlen < 40 || bitlen > 168) { gpsd_log(errout, LOG_WARN, "AIVDM message type 25 size not between 40 to 168 bits (%zd).\n", bitlen); return false; } ais->type25.addressed = (bool)UBITS(38, 1); ais->type25.structured = (bool)UBITS(39, 1); if (bitlen < (unsigned)(40 + (16*ais->type25.structured) + (30*ais->type25.addressed))) { gpsd_log(errout, LOG_WARN, "AIVDM message type 25 too short for mode.\n"); return false; } if (ais->type25.addressed) ais->type25.dest_mmsi = UBITS(40, 30); if (ais->type25.structured) ais->type25.app_id = UBITS(40+ais->type25.addressed*30,16); ais->type25.bitcount = bitlen - 40 - 16*ais->type25.structured; /* bit 40 is exactly 5 bytes in; 2 bytes is 16 bits */ (void)memcpy(ais->type25.bitdata, (char *)bits+5 + 2 * ais->type25.structured, BITS_TO_BYTES(ais->type25.bitcount)); /* discard MMSI if addressed */ if (ais->type25.addressed) { shiftleft((unsigned char *)ais->type25.bitdata, ais->type25.bitcount, 30); ais->type25.bitcount -= 30; } break; case 26: /* Binary Message, Multiple Slot */ RANGE_CHECK(60, 1004); ais->type26.addressed = (bool)UBITS(38, 1); ais->type26.structured = (bool)UBITS(39, 1); if ((signed)bitlen < 40 + 16*ais->type26.structured + 30*ais->type26.addressed + 20) { gpsd_log(errout, LOG_WARN, "AIVDM message type 26 too short for mode.\n"); return false; } if (ais->type26.addressed) ais->type26.dest_mmsi = UBITS(40, 30); if (ais->type26.structured) ais->type26.app_id = UBITS(40+ais->type26.addressed*30,16); ais->type26.bitcount = bitlen - 60 - 16*ais->type26.structured; (void)memcpy(ais->type26.bitdata, (unsigned char *)bits+5 + 2 * ais->type26.structured, BITS_TO_BYTES(ais->type26.bitcount)); /* discard MMSI if addressed */ if (ais->type26.addressed) { shiftleft((unsigned char *)ais->type26.bitdata, ais->type26.bitcount, 30); ais->type26.bitcount -= 30; } break; case 27: /* Long Range AIS Broadcast message */ if (bitlen != 96 && bitlen != 168) { gpsd_log(errout, LOG_WARN, "unexpected AIVDM message type 27 (%zd).\n", bitlen); return false; } if (bitlen == 168) { /* * This is an implementation error observed in the wild, * sending a full 168-bit slot rather than just 96 bits. */ gpsd_log(errout, LOG_WARN, "oversized 169=8-bit AIVDM message type 27.\n"); } ais->type27.accuracy = (bool)UBITS(38, 1); ais->type27.raim = UBITS(39, 1)!=0; ais->type27.status = UBITS(40, 4); ais->type27.lon = SBITS(44, 18); ais->type27.lat = SBITS(62, 17); ais->type27.speed = UBITS(79, 6); ais->type27.course = UBITS(85, 9); ais->type27.gnss = (bool)UBITS(94, 1); break; default: gpsd_log(errout, LOG_ERROR, "Unparsed AIVDM message type %d.\n",ais->type); return false; } /* *INDENT-ON* */ #undef UCHARS #undef SBITS #undef UBITS /* data is fully decoded */ return true; }
* Default lamp values are also tracked per-player. They are guaranteed to be * all off at the start of a player's game, and they are saved/restored in * multiplayer games. The secondary/lightshow values are transient and are not * saved this way. * */ #include <freewpc.h> __fastram__ lamp_set lamp_matrix; lamp_set lamp_flash_matrix; __fastram__ lamp_set lamp_flash_matrix_now; U8 bit_matrix[BITS_TO_BYTES (MAX_FLAGS)]; U8 global_bits[BITS_TO_BYTES (MAX_GLOBAL_FLAGS)]; #ifdef CONFIG_LAMP_STROBE16 typedef U16 lamp_strobe_t; #else typedef U8 lamp_strobe_t; #endif __fastram__ lamp_strobe_t lamp_strobe_mask; __fastram__ U8 lamp_strobe_column; __fastram__ U8 lamp_power_timer; U8 lamp_power_level;
int GrInternalString0 (int x, int y, char *s) { unsigned char * fp; char *text_ptr, *next_row, *text_ptr1; int r, BitMask, i, bits, width, spacing, letter, underline; int skip_lines = 0; unsigned int VideoOffset, VideoOffset1; ubyte *palette = grdCurCanv->cv_bitmap.bm_palette; if (!palette) palette = gamePalette; if (FG_COLOR.rgb) { FG_COLOR.rgb = 0; FG_COLOR.index = GrFindClosestColor (gamePalette, FG_COLOR.color.red, FG_COLOR.color.green, FG_COLOR.color.blue); } if (BG_COLOR.rgb) { BG_COLOR.rgb = 0; BG_COLOR.index = GrFindClosestColor (gamePalette, BG_COLOR.color.red, BG_COLOR.color.green, BG_COLOR.color.blue); } bits=0; VideoOffset1 = y * ROWSIZE + x; next_row = s; while (next_row != NULL) { text_ptr1 = next_row; next_row = NULL; if (x == 0x8000) { //centered int xx = GetCenteredX (text_ptr1); VideoOffset1 = y * ROWSIZE + xx; } for (r = 0; r < FHEIGHT; r++) { text_ptr = text_ptr1; VideoOffset = VideoOffset1; while (*text_ptr) { if (*text_ptr == '\n') { next_row = &text_ptr[1]; break; } if (*text_ptr == CC_COLOR) { FG_COLOR.index = *(text_ptr+1); FG_COLOR.rgb = 0; text_ptr += 2; continue; } if (*text_ptr == CC_LSPACING) { skip_lines = * (text_ptr+1) - '0'; text_ptr += 2; continue; } underline = 0; if (*text_ptr == CC_UNDERLINE) { if ((r == FBASELINE + 2) || (r == FBASELINE + 3)) underline = 1; text_ptr++; } get_char_width (text_ptr[0], text_ptr[1], &width, &spacing); letter = *text_ptr - FMINCHAR; if (!INFONT (letter)) { //not in font, draw as space VideoOffset += spacing; text_ptr++; continue; } if (FFLAGS & FT_PROPORTIONAL) fp = FCHARS [letter]; else fp = FDATA + letter * BITS_TO_BYTES (width)*FHEIGHT; if (underline) for (i = 0; i < width; i++) DATA[VideoOffset++] = (unsigned char) FG_COLOR.index; else { fp += BITS_TO_BYTES (width)*r; BitMask = 0; for (i = 0; i < width; i++) { if (BitMask == 0) { bits = *fp++; BitMask = 0x80; } if (bits & BitMask) DATA[VideoOffset++] = (unsigned char) FG_COLOR.index; else DATA[VideoOffset++] = (unsigned char) BG_COLOR.index; BitMask >>= 1; } } VideoOffset += spacing-width; //for kerning text_ptr++; } VideoOffset1 += ROWSIZE; y++; } y += skip_lines; VideoOffset1 += ROWSIZE * skip_lines; skip_lines = 0; } return 0; }
int GrInternalString0m (int x, int y, char *s) { unsigned char * fp; char * text_ptr, * next_row, * text_ptr1; int r, BitMask, i, bits, width, spacing, letter, underline; int skip_lines = 0; char c; int orig_color; unsigned int VideoOffset, VideoOffset1; if (FG_COLOR.rgb) { FG_COLOR.rgb = 0; FG_COLOR.index = GrFindClosestColor (FONT->ft_parent_bitmap.bm_palette, FG_COLOR.color.red, FG_COLOR.color.green, FG_COLOR.color.blue); } if (BG_COLOR.rgb) { BG_COLOR.rgb = 0; BG_COLOR.index = GrFindClosestColor (FONT->ft_parent_bitmap.bm_palette, BG_COLOR.color.red, BG_COLOR.color.green, BG_COLOR.color.blue); } orig_color = FG_COLOR.index;//to allow easy reseting to default string color with colored strings -MPM bits=0; VideoOffset1 = y * ROWSIZE + x; next_row = s; FG_COLOR.rgb = 0; while (next_row != NULL) { text_ptr1 = next_row; next_row = NULL; if (x==0x8000) { //centered int xx = GetCenteredX (text_ptr1); VideoOffset1 = y * ROWSIZE + xx; } for (r=0; r<FHEIGHT; r++) { text_ptr = text_ptr1; VideoOffset = VideoOffset1; while ((c = *text_ptr)) { if (c == '\n') { next_row = &text_ptr[1]; break; } if (c == CC_COLOR) { FG_COLOR.index = * (++text_ptr); text_ptr++; continue; } if (c == CC_LSPACING) { skip_lines = * (++text_ptr) - '0'; text_ptr++; continue; } underline = 0; if (c == CC_UNDERLINE) { if ((r==FBASELINE+2) || (r==FBASELINE+3)) underline = 1; c = * (++text_ptr); } get_char_width (c, text_ptr[1], &width, &spacing); letter = c - FMINCHAR; if (!INFONT (letter) || c <= 0x06) { //not in font, draw as space #if 0 CHECK_EMBEDDED_COLORS () #else if ((c >= 1) && (c <= 3)) { if (*++text_ptr) { if (grMsgColorLevel >= c) { FG_COLOR.rgb = 1; FG_COLOR.color.red = text_ptr [0] - 128; FG_COLOR.color.green = text_ptr [1] - 128; FG_COLOR.color.blue = text_ptr [2] - 128; FG_COLOR.color.alpha = 0; } text_ptr += 3; } } else if ((c >= 4) && (c <= 6)) { if (grMsgColorLevel >= *text_ptr - 3) { FG_COLOR.index = orig_color; FG_COLOR.rgb = 0; } text_ptr++; } #endif else { VideoOffset += spacing; text_ptr++; } continue; } if (FFLAGS & FT_PROPORTIONAL) fp = FCHARS[letter]; else fp = FDATA + letter * BITS_TO_BYTES (width) * FHEIGHT; if (underline) for (i=0; i< width; i++) DATA[VideoOffset++] = (unsigned int) FG_COLOR.index; else { fp += BITS_TO_BYTES (width)*r; BitMask = 0; for (i=0; i< width; i++) { if (BitMask==0) { bits = *fp++; BitMask = 0x80; } if (bits & BitMask) DATA[VideoOffset++] = (unsigned int) FG_COLOR.index; else VideoOffset++; BitMask >>= 1; } } text_ptr++; VideoOffset += spacing-width; } VideoOffset1 += ROWSIZE; y++; } y += skip_lines; VideoOffset1 += ROWSIZE * skip_lines; skip_lines = 0; }
Packet* RakClient::Receive( void ) { Packet * packet = RakPeer::Receive(); // Intercept specific client / server feature packets if ( packet ) { RakNet::BitStream bitStream( ( char* ) packet->data, packet->length, false ); int i; if ( packet->data[ 0 ] == ID_CONNECTION_REQUEST_ACCEPTED ) { // ConnectionAcceptStruct cas; // cas.Deserialize(bitStream); // unsigned short remotePort; // PlayerID externalID; PlayerIndex playerIndex; RakNet::BitStream inBitStream((char*)packet->data, packet->length, false); inBitStream.IgnoreBits(8); // ID_CONNECTION_REQUEST_ACCEPTED inBitStream.IgnoreBits(8 * sizeof(unsigned short)); //inBitStream.Read(remotePort); inBitStream.IgnoreBits(8 * sizeof(unsigned int)); //inBitStream.Read(externalID.binaryAddress); inBitStream.IgnoreBits(8 * sizeof(unsigned short)); //inBitStream.Read(externalID.port); inBitStream.Read(playerIndex); localPlayerIndex = playerIndex; packet->playerIndex = playerIndex; } else if ( packet->data[ 0 ] == ID_REMOTE_NEW_INCOMING_CONNECTION || packet->data[ 0 ] == ID_REMOTE_EXISTING_CONNECTION || packet->data[ 0 ] == ID_REMOTE_DISCONNECTION_NOTIFICATION || packet->data[ 0 ] == ID_REMOTE_CONNECTION_LOST ) { bitStream.IgnoreBits( 8 ); // Ignore identifier bitStream.Read( packet->playerId.binaryAddress ); bitStream.Read( packet->playerId.port ); if ( bitStream.Read( ( unsigned short& ) packet->playerIndex ) == false ) { DeallocatePacket( packet ); return 0; } if ( packet->data[ 0 ] == ID_REMOTE_DISCONNECTION_NOTIFICATION || packet->data[ 0 ] == ID_REMOTE_CONNECTION_LOST ) { i = GetOtherClientIndexByPlayerID( packet->playerId ); if ( i >= 0 ) otherClients[ i ].isActive = false; } } else if ( packet->data[ 0 ] == ID_REMOTE_STATIC_DATA ) { bitStream.IgnoreBits( 8 ); // Ignore identifier bitStream.Read( packet->playerId.binaryAddress ); bitStream.Read( packet->playerId.port ); bitStream.Read( packet->playerIndex ); // ADDED BY KURI i = GetOtherClientIndexByPlayerID( packet->playerId ); if ( i < 0 ) i = GetFreeOtherClientIndex(); if ( i >= 0 ) { otherClients[ i ].playerId = packet->playerId; otherClients[ i ].isActive = true; otherClients[ i ].staticData.Reset(); // The static data is what is left over in the stream otherClients[ i ].staticData.Write( ( char* ) bitStream.GetData() + BITS_TO_BYTES( bitStream.GetReadOffset() ), bitStream.GetNumberOfBytesUsed() - BITS_TO_BYTES( bitStream.GetReadOffset() ) ); } } else if ( packet->data[ 0 ] == ID_BROADCAST_PINGS ) { PlayerID playerId; int index; bitStream.IgnoreBits( 8 ); // Ignore identifier for ( i = 0; i < 32; i++ ) { if ( bitStream.Read( playerId.binaryAddress ) == false ) break; // No remaining data! bitStream.Read( playerId.port ); index = GetOtherClientIndexByPlayerID( playerId ); if ( index >= 0 ) bitStream.Read( otherClients[ index ].ping ); else { index = GetFreeOtherClientIndex(); if ( index >= 0 ) { otherClients[ index ].isActive = true; bitStream.Read( otherClients[ index ].ping ); otherClients[ index ].playerId = playerId; otherClients[ index ].staticData.Reset(); } else bitStream.IgnoreBits( sizeof( short ) * 8 ); } } DeallocatePacket( packet ); return 0; } else if ( packet->data[ 0 ] == ID_TIMESTAMP && packet->length == sizeof(unsigned char)+sizeof(unsigned int)+sizeof(unsigned char)+sizeof(unsigned int)+sizeof(unsigned int) ) { /* RakNet::BitStream s_BitS( (char *)packet->data, SetRandomNumberSeedStruct_Size, false ); SetRandomNumberSeedStruct s; s.Deserialize( s_BitS ); */ RakNet::BitStream inBitStream((char *)packet->data, packet->length, false); /* unsigned char ts; unsigned int timeStamp; unsigned char typeId; unsigned int seed; unsigned int nextSeed; */ unsigned int timeStamp; unsigned char typeId; unsigned int in_seed; unsigned int in_nextSeed; inBitStream.IgnoreBits(8); // ID_TIMESTAMP inBitStream.Read(timeStamp); inBitStream.Read(typeId); // ID_SET_RANDOM_NUMBER_SEED ? // Check to see if this is a user TIMESTAMP message which // accidentally has length SetRandomNumberSeedStruct_Size if ( typeId != ID_SET_RANDOM_NUMBER_SEED ) return packet; inBitStream.Read(in_seed); inBitStream.Read(in_nextSeed); seed = in_seed; nextSeed = in_nextSeed; nextSeedUpdate = timeStamp + 9000; // Seeds are updated every 9 seconds DeallocatePacket( packet ); return 0; } } return packet; }
void PacketLogger::OnInternalPacket(InternalPacket *internalPacket, unsigned frameNumber, PlayerID remoteSystemID, RakNetTime time, bool isSend) { char str[256]; char sendType[4]; PlayerID localPlayerId; localPlayerId = rakPeer->GetInternalID(); if (isSend) strcpy(sendType, "Snd"); else strcpy(sendType, "Rcv"); // TODO - put this back in a different form /* if (internalPacket->isAcknowledgement) { if (printAcks) { if (printId==false) sprintf(str, "%s,Ack,%5i,%5i, NIL, 1,%i,%u:%i,%u:%i\n",sendType, internalPacket->messageNumber,frameNumber,time, localPlayerId.binaryAddress, localPlayerId.port, remoteSystemID.binaryAddress, remoteSystemID.port); else sprintf(str, "%s,Ack,%i,%i,NIL,1,%i,%u:%i,%u:%i\n",sendType, internalPacket->messageNumber,frameNumber,time, localPlayerId.binaryAddress, localPlayerId.port, remoteSystemID.binaryAddress, remoteSystemID.port); } else str[0]=0; } else */ { if (internalPacket->data[0]==ID_TIMESTAMP && internalPacket->data[sizeof(unsigned char)+sizeof(RakNetTime)]!=ID_RPC) { if (printId==false) { sprintf(str, "%s,Tms,%5i,%5i,%5i,%5i,%i,%u:%i,%u:%i\n",sendType, internalPacket->messageNumber,frameNumber, internalPacket->data[1+sizeof(int)], internalPacket->dataBitLength,time, localPlayerId.binaryAddress, localPlayerId.port, remoteSystemID.binaryAddress, remoteSystemID.port); } else { sprintf(str, "%s,Tms,%i,%i,%s,%i,%i,%u:%i,%u:%i\n",sendType, internalPacket->messageNumber,frameNumber, IDTOString(internalPacket->data[1+sizeof(int)]), internalPacket->dataBitLength,time, localPlayerId.binaryAddress, localPlayerId.port, remoteSystemID.binaryAddress, remoteSystemID.port); } } else if (internalPacket->data[0]==ID_RPC || (internalPacket->dataBitLength>(sizeof(unsigned char)+sizeof(RakNetTime))*8 && internalPacket->data[0]==ID_TIMESTAMP && internalPacket->data[sizeof(unsigned char)+sizeof(RakNetTime)]==ID_RPC)) { bool hasTimestamp; unsigned int bitsOfData; bool nameIsEncoded; unsigned char uniqueIdentifier[256]; RPCIndex rpcIndex; RPCMap *rpcMap; RakNet::BitStream rpcDecode(internalPacket->data, BITS_TO_BYTES(internalPacket->dataBitLength), false); rpcDecode.IgnoreBits(8); if (internalPacket->data[0]==ID_TIMESTAMP) rpcDecode.IgnoreBits(sizeof(unsigned char)+sizeof(RakNetTime)); rpcDecode.Read(nameIsEncoded); if (nameIsEncoded) { stringCompressor->DecodeString((char*)uniqueIdentifier, 256, &rpcDecode); } else { rpcDecode.ReadCompressed( rpcIndex ); RPCNode *rpcNode; rpcMap = rakPeer->GetRPCMap(isSend==true ? remoteSystemID : UNASSIGNED_PLAYER_ID); if (rpcMap) rpcNode = rpcMap->GetNodeFromIndex(rpcIndex); else rpcNode=0; if (rpcMap && rpcNode) strcpy((char*)uniqueIdentifier, rpcNode->uniqueIdentifier); else strcpy((char*)uniqueIdentifier, "[UNKNOWN]"); } rpcDecode.Read(hasTimestamp); rpcDecode.ReadCompressed(bitsOfData); if (hasTimestamp) sprintf(str, "%s,RpT,%5i,%5i,%s,%5i,%i,%u:%i,%u:%i\n",sendType, internalPacket->messageNumber,frameNumber, uniqueIdentifier, internalPacket->dataBitLength,time, localPlayerId.binaryAddress, localPlayerId.port, remoteSystemID.binaryAddress, remoteSystemID.port); else sprintf(str, "%s,Rpc,%5i,%5i,%s,%5i,%i,%u:%i,%u:%i\n",sendType, internalPacket->messageNumber,frameNumber, uniqueIdentifier, internalPacket->dataBitLength,time, localPlayerId.binaryAddress, localPlayerId.port, remoteSystemID.binaryAddress, remoteSystemID.port); } else { if (printId==false) { sprintf(str, "%s,Nrm,%5i,%5i,%5i,%5i,%i,%u:%i,%u:%i\n",sendType, internalPacket->messageNumber,frameNumber, internalPacket->data[0], internalPacket->dataBitLength,time, localPlayerId.binaryAddress, localPlayerId.port, remoteSystemID.binaryAddress, remoteSystemID.port); } else { sprintf(str, "%s,Nrm,%i,%i,%s,%i,%i,%u:%i,%u:%i\n",sendType, internalPacket->messageNumber,frameNumber, IDTOString(internalPacket->data[0]), internalPacket->dataBitLength,time, localPlayerId.binaryAddress, localPlayerId.port, remoteSystemID.binaryAddress, remoteSystemID.port); } } } WriteLog(str); }
/* * writeImageBits - writes the bits for the image */ static bool writeImageBits( FILE *fp, img_node *node ) { WPI_PRES pres; WPI_PRES mempres; HDC memdc; ULONG byte_count; img_node *new_image; BITMAPINFO2 *bmi; HBITMAP oldbitmap; HBITMAP inverse_bitmap; HBITMAP clr_bitmap; BYTE *buffer; bool ok; ok = true; pres = _wpi_getpres( HWND_DESKTOP ); mempres = _wpi_createcompatiblepres( pres, Instance, &memdc ); _wpi_releasepres( HWND_DESKTOP, pres ); for( new_image = node; new_image != NULL; new_image = new_image->nexticon ) { bmi = GetAndBitmapInfo(new_image); if( bmi == NULL ) { ok = false; break; } /* * first we write the PM XOR mask (inverse mask) then the PM AND * mask (and mask) and then the PM colour mask (xor mask). */ byte_count = BITS_TO_BYTES( new_image->width, new_image->height ); buffer = MemAlloc( byte_count ); inverse_bitmap = CreateInverseBitmap( new_image->handbitmap, new_image->hxorbitmap ); oldbitmap = _wpi_selectobject( mempres, inverse_bitmap ); GpiQueryBitmapBits( mempres, 0, new_image->height, buffer, bmi ); fwrite( buffer, sizeof( BYTE ), byte_count, fp ); _wpi_selectobject( mempres, oldbitmap ); _wpi_deletebitmap( inverse_bitmap ); oldbitmap = _wpi_selectobject( mempres, new_image->handbitmap ); GpiQueryBitmapBits( mempres, 0, new_image->height, buffer, bmi ); fwrite( buffer, sizeof( BYTE ), byte_count, fp ); _wpi_selectobject( mempres, oldbitmap ); MemFree( buffer ); FreeDIBitmapInfo( bmi ); bmi = GetXorBitmapInfo( new_image ); if( bmi == NULL ) { ok = false; break; } clr_bitmap = CreateColourBitmap( new_image->handbitmap, new_image->hxorbitmap ); oldbitmap = _wpi_selectobject( mempres, clr_bitmap ); byte_count = BITS_TO_BYTES( new_image->width * new_image->bitcount, new_image->height ); buffer = MemAlloc( byte_count ); GpiQueryBitmapBits( mempres, 0, node->height, buffer, bmi ); fwrite( buffer, sizeof( BYTE ), byte_count, fp ); MemFree( buffer ); FreeDIBitmapInfo( bmi ); _wpi_selectobject( mempres, oldbitmap ); _wpi_deletebitmap( clr_bitmap ); } _wpi_deletecompatiblepres( mempres, memdc ); return( ok ); } /* writeImageBits */
static ssize_t chm_imp_configure (mphf_t *mphf, request_t *fork_req){ // {{{ ssize_t ret; backend_t *t; backend_t *be_g = NULL; backend_t *be_v = NULL; backend_t *be_e = NULL; char *backend = NULL; uintmax_t nelements_min = CAPACITY_MIN_DEFAULT; uintmax_t nelements_step = CAPACITY_STEP_DEFAULT; uintmax_t nelements_mul = CAPACITY_MUL_DEFAULT; uintmax_t bi_value = VALUE_BITS_DEFAULT; uintmax_t readonly = 0; chm_imp_t *data = (chm_imp_t *)&mphf->data; if( (data->status & FILLED) == 0){ hash_data_copy(ret, TYPE_UINTT, nelements_min, mphf->config, HK(nelements_min)); hash_data_copy(ret, TYPE_UINTT, nelements_step, mphf->config, HK(nelements_step)); hash_data_copy(ret, TYPE_UINTT, nelements_mul, mphf->config, HK(nelements_mul)); hash_data_copy(ret, TYPE_UINTT, bi_value, mphf->config, HK(value_bits)); // number of bits per value to store hash_data_copy(ret, TYPE_UINTT, readonly, mphf->config, HK(readonly)); // run in read-only mode hash_data_copy(ret, TYPE_STRINGT, backend, mphf->config, HK(backend_g)); if(ret == 0){ be_g = t = backend_acquire(backend); if(fork_req){ be_g = backend_fork(t, fork_req); backend_destroy(t); } } hash_data_copy(ret, TYPE_STRINGT, backend, mphf->config, HK(backend_v)); if(ret == 0){ be_v = t = backend_acquire(backend); if(fork_req){ be_v = backend_fork(t, fork_req); backend_destroy(t); } } hash_data_copy(ret, TYPE_STRINGT, backend, mphf->config, HK(backend_e)); if(ret == 0){ be_e = t = backend_acquire(backend); if(fork_req){ be_e = backend_fork(t, fork_req); backend_destroy(t); } } if(be_g == NULL) return error("backend chm_imp parameter backend_g invalid"); if(be_v == NULL || be_e == NULL || readonly != 0){ data->status &= ~WRITEABLE; }else{ data->status |= WRITEABLE; } data->be_g = be_g; data->be_v = be_v; data->be_e = be_e; data->nelements_min = nelements_min; data->nelements_step = nelements_step; data->nelements_mul = nelements_mul; data->bi_value = bi_value; data->bt_value = BITS_TO_BYTES(data->bi_value); data->status |= FILLED; } return 0; } // }}}
int GrInternalString0m (int x, int y, const char *s) { ubyte* fp; const char* textP, * nextRowP, * text_ptr1; int r, mask, i, bits, width, spacing, letter, underline; int skip_lines = 0; char c; int origColor; uint videoOffset, videoOffset1; ubyte* videoBuffer = CCanvas::Current ()->Buffer (); int rowSize = CCanvas::Current ()->RowSize (); tFont font; if (CCanvas::Current ()->FontColor (0).rgb) { CCanvas::Current ()->FontColor (0).rgb = 0; CCanvas::Current ()->FontColor (0).index = fontManager.Current ()->ParentBitmap ().Palette ()->ClosestColor (CCanvas::Current ()->FontColor (0).color.red, CCanvas::Current ()->FontColor (0).color.green, CCanvas::Current ()->FontColor (0).color.blue); } if (CCanvas::Current ()->FontColor (1).rgb) { CCanvas::Current ()->FontColor (1).rgb = 0; CCanvas::Current ()->FontColor (1).index = fontManager.Current ()->ParentBitmap ().Palette ()->ClosestColor (CCanvas::Current ()->FontColor (1).color.red, CCanvas::Current ()->FontColor (1).color.green, CCanvas::Current ()->FontColor (1).color.blue); } origColor = CCanvas::Current ()->FontColor (0).index;//to allow easy reseting to default string color with colored strings -MPM bits=0; videoOffset1 = y * rowSize + x; fontManager.Current ()->GetInfo (font); nextRowP = s; CCanvas::Current ()->FontColor (0).rgb = 0; while (nextRowP != NULL) { text_ptr1 = nextRowP; nextRowP = NULL; if (x==0x8000) { //centered int xx = fontManager.Current ()->GetCenteredX (text_ptr1); videoOffset1 = y * rowSize + xx; } for (r = 0; r < font.height; r++) { textP = text_ptr1; videoOffset = videoOffset1; while ((c = *textP)) { if (c == '\n') { nextRowP = textP + 1; break; } if (c == CC_COLOR) { CCanvas::Current ()->FontColor (0).index = * (++textP); textP++; continue; } if (c == CC_LSPACING) { skip_lines = * (++textP) - '0'; textP++; continue; } underline = 0; if (c == CC_UNDERLINE) { if ((r==font.baseLine+2) || (r==font.baseLine+3)) underline = 1; c = * (++textP); } fontManager.Current ()->GetCharWidth (c, textP[1], width, spacing); letter = c - font.minChar; if (c <= 0x06) { //not in font, draw as space textP = ScanEmbeddedColors (c, textP, origColor, 0, 1); continue; } if (!fontManager.Current ()->InFont (letter)) { videoOffset += spacing; textP++; } if (font.flags & FT_PROPORTIONAL) fp = font.chars[letter]; else fp = font.data + letter * BITS_TO_BYTES (width) * font.height; if (underline) for (i = 0; i < width; i++) videoBuffer [videoOffset++] = (uint) CCanvas::Current ()->FontColor (0).index; else { fp += BITS_TO_BYTES (width) * r; mask = 0; for (i = 0; i < width; i++) { if (mask == 0) { bits = *fp++; mask = 0x80; } if (bits & mask) videoBuffer [videoOffset++] = (uint) CCanvas::Current ()->FontColor (0).index; else videoOffset++; mask >>= 1; } } textP++; videoOffset += spacing-width; } videoOffset1 += rowSize; y++; } y += skip_lines; videoOffset1 += rowSize * skip_lines; skip_lines = 0; } return 0; }
/* * IEStretchBlt */ BOOL IEStretchBlt( WPI_PRES hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, WPI_PRES hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, DWORD fdwRop, int bitcount ) { POINT slines; POINT dlines; POINT num_strips; unsigned long linesize; int x, y; int sw, sh, dw, dh; WPI_PRES srcpres; HDC srcdc; HBITMAP oldbitmap; HBITMAP newbitmap; num_strips.x = nWidthDest / 256; num_strips.x++; #if 0 if( nWidthDest > 32 ) { /* use the version that returns exact bytes needed for bits */ linesize = BITS_INTO_BYTES( (unsigned long)(nWidthDest * bitcount), 1 ); } else { /* use the version that rounds up to 32 bits */ linesize = BITS_TO_BYTES( (unsigned long)(nWidthDest * bitcount), 1 ); } #else /* use the version that rounds up to 32 bits */ linesize = BITS_TO_BYTES( (unsigned long)(nWidthDest * bitcount), 1 ); #endif num_strips.y = ((unsigned long)nHeightDest * linesize) / (16 * 1024); num_strips.y++; if( num_strips.x > nWidthSrc ) { num_strips.x = nWidthSrc; } else if( num_strips.x < nWidthSrc ) { num_strips.x += num_strips.x % 2; } if( num_strips.y > nHeightSrc ) { num_strips.y = nHeightSrc; } else if( num_strips.y < nHeightSrc ) { num_strips.y += num_strips.y % 2; } slines.x = nWidthSrc / num_strips.x; dlines.x = ((unsigned long)slines.x * (unsigned long)nWidthDest) / (unsigned long)nWidthSrc; slines.y = nHeightSrc / num_strips.y; dlines.y = ((unsigned long)slines.y * (unsigned long)nHeightDest) / (unsigned long)nHeightSrc; srcpres = _wpi_createcompatiblepres( hdcDest, Instance, &srcdc ); newbitmap = _wpi_createcompatiblebitmap( hdcDest, dlines.x, dlines.y ); oldbitmap = _wpi_selectobject( srcpres, newbitmap ); sw = slines.x; dw = dlines.x; for( x = 0; slines.x * x <= nWidthSrc; x++ ) { if( slines.x * x + sw > nWidthSrc ) { sw = nWidthSrc - x * slines.x; dw = nWidthDest - x * dlines.x; } sh = slines.y; dh = dlines.y; for( y = 0; slines.y * y <= nHeightSrc; y++ ) { if( slines.y * y + sh > nHeightSrc ) { sh = nHeightSrc - y * slines.y; dh = nHeightDest - y * dlines.y; } _wpi_stretchblt( srcpres, 0, 0, dw, dh, hdcSrc, nXOriginSrc + slines.x * x, nYOriginSrc + slines.y * y, sw, sh, fdwRop ); _wpi_bitblt( hdcDest, nXOriginDest + dlines.x * x, nYOriginDest + dlines.y * y, dw, dh, srcpres, 0, 0, SRCCOPY ); } } _wpi_selectobject( srcpres, oldbitmap ); _wpi_deleteobject( newbitmap ); _wpi_deletecompatiblepres( srcpres, srcdc ); return( TRUE ); } /* IEStretchBlt */
int GrInternalStringClippedM (int x, int y, const char *s) { ubyte * fp; const char * textP, * nextRowP, * text_ptr1; int r, mask, i, bits, width, spacing, letter, underline; int x1 = x, last_x; tFont font; fontManager.Current ()->GetInfo (font); bits = 0; nextRowP = s; CCanvas::Current ()->FontColor (0).rgb = 0; while (nextRowP != NULL) { text_ptr1 = nextRowP; nextRowP = NULL; x = x1; if (x==0x8000) //centered x = fontManager.Current ()->GetCenteredX (text_ptr1); last_x = x; for (r = 0; r < font.height; r++) { x = last_x; textP = text_ptr1; while (*textP) { if (*textP == '\n') { nextRowP = &textP[1]; break; } if (*textP == CC_COLOR) { CCanvas::Current ()->FontColor (0).index = * (textP+1); textP += 2; continue; } if (*textP == CC_LSPACING) { Int3 (); // Warning: skip lines not supported for clipped strings. textP += 2; continue; } underline = 0; if (*textP == CC_UNDERLINE) { if ((r == font.baseLine + 2) || (r == font.baseLine + 3)) underline = 1; textP++; } fontManager.Current ()->GetCharWidth (textP[0], textP[1], width, spacing); letter = *textP-font.minChar; if (!fontManager.Current ()->InFont (letter)) { //not in font, draw as space x += spacing; textP++; continue; } if (font.flags & FT_PROPORTIONAL) fp = font.chars[letter]; else fp = font.data + letter * BITS_TO_BYTES (width)*font.height; if (underline) { for (i = 0; i < width; i++) { CCanvas::Current ()->SetColor (CCanvas::Current ()->FontColor (0).index); DrawPixelClipped (x++, y); } } else { fp += BITS_TO_BYTES (width)*r; mask = 0; for (i = 0; i< width; i++) { if (mask==0) { bits = *fp++; mask = 0x80; } if (bits & mask) { CCanvas::Current ()->SetColor (CCanvas::Current ()->FontColor (0).index); DrawPixelClipped (x++, y); } else { x++; } mask >>= 1; } } x += spacing-width; //for kerning textP++; } y++; } } font.parentBitmap.SetBuffer (NULL); //beware of the destructor! return 0; }
static HBITMAP WRReadBitmap( BYTE *data, long offset, BOOL core, bitmap_info *info ) { DWORD size; /* generic size - used repeatedly */ BYTE _HUGE *mask_ptr; /* pointer to bit array in memory */ HDC hdc; HPALETTE new_palette, old_palette; BITMAPINFO *bm_info = NULL; BITMAPCOREINFO *bm_core = NULL; HBITMAP bitmap_handle; int pos; bitmap_handle = (HBITMAP)NULL; if( core ) { bm_core = WRReadCoreInfo( &data ); if( bm_core == NULL ) { return( bitmap_handle ); } size = BITS_TO_BYTES( bm_core->bmciHeader.bcWidth * bm_core->bmciHeader.bcBitCount, bm_core->bmciHeader.bcHeight ); } else { bm_info = WRReadDIBInfo( &data ); if( bm_info == NULL ) { return( bitmap_handle ); } size = BITS_TO_BYTES( bm_info->bmiHeader.biWidth * bm_info->bmiHeader.biBitCount, bm_info->bmiHeader.biHeight ); } pos = offset; mask_ptr = __halloc( size, 1 ); if( mask_ptr != NULL ) { WRReadInPieces( mask_ptr, data, size ); if( core ) { BITMAPCOREHEADER *h; h = &bm_core->bmciHeader; /* * This will cause a GP Fault! */ bitmap_handle = CreateBitmap( h->bcWidth, h->bcHeight, h->bcPlanes, h->bcBitCount, mask_ptr ); } else { if( bm_info->bmiHeader.biBitCount < 9 ) { /* Bitmap has palette, create it */ new_palette = CreateDIBPalette( bm_info ); if( new_palette != NULL ) { hdc = GetDC( (HWND)NULL ); old_palette = SelectPalette( hdc, new_palette, FALSE ); RealizePalette( hdc ); bitmap_handle = CreateDIBitmap( hdc, &bm_info->bmiHeader, CBM_INIT, mask_ptr, bm_info, DIB_RGB_COLORS ); SelectPalette( hdc, old_palette, FALSE ); DeleteObject( new_palette ); ReleaseDC( (HWND)NULL, hdc ); } } else { /* Bitmap with no palette*/ hdc = GetDC( (HWND)NULL ); bitmap_handle = CreateDIBitmap( hdc, &bm_info->bmiHeader, CBM_INIT, mask_ptr, bm_info, DIB_RGB_COLORS ); ReleaseDC( (HWND)NULL, hdc ); } } __hfree( mask_ptr ); } if( core ) { if( info != NULL ) { info->u.bm_core = bm_core; } else { MemFree( bm_core ); } } else { if( info != NULL ) { info->u.bm_info = bm_info; } else { MemFree( bm_info ); } } return( bitmap_handle ); }
/* * expand group->newsrc information if group->xmax is larger than * group->newsrc.xmax or min is smaller than group->newsrc.xmin. */ void expand_bitmap( struct t_group *group, long min) { long bitlen; long first; long tmp; long max; t_bool need_full_copy = FALSE; /* calculate new max */ if (group->newsrc.xmax > group->xmax) max = group->newsrc.xmax; else max = group->xmax; /* adjust min */ if (!min) min = group->newsrc.xmin; /* calculate first */ if (min >= group->newsrc.xmin) first = group->newsrc.xmin; else first = group->newsrc.xmin - ((group->newsrc.xmin - min + (NBITS - 1)) & ~(NBITS - 1)); /* adjust first */ if (first > group->newsrc.xmax + 1) first = first - ((first - (group->newsrc.xmax + 1) + (NBITS - 1)) & ~(NBITS - 1)); /* check first */ if (first < 1) { need_full_copy = TRUE; first = 1; } bitlen = max - first + 1; if (bitlen <= 0) { bitlen = 0; FreeIfNeeded(group->newsrc.xbitmap); group->newsrc.xbitmap = (t_bitmap *) 0; #ifdef DEBUG_NEWSRC debug_print_comment("expand_bitmap: group->newsrc.bitlen == 0"); #endif /* DEBUG_NEWSRC */ } else if (group->newsrc.xbitmap == NULL) { group->newsrc.xbitmap = my_malloc(BITS_TO_BYTES(bitlen)); if (group->newsrc.xmin > first) NSETRNG0(group->newsrc.xbitmap, 0L, group->newsrc.xmin - first - 1L); if (bitlen > group->newsrc.xmin - first) NSETRNG1(group->newsrc.xbitmap, group->newsrc.xmin - first, bitlen - 1); #ifdef DEBUG_NEWSRC debug_print_comment("expand_bitmap: group->newsrc.xbitmap == NULL"); #endif /* DEBUG_NEWSRC */ } else if (need_full_copy) { t_bitmap *newbitmap; newbitmap = my_malloc(BITS_TO_BYTES(bitlen)); /* Copy over old bitmap */ /* TODO: change to use shift */ for (tmp = group->newsrc.xmin; tmp <= group->newsrc.xmax; tmp++) { if (NTEST(group->newsrc.xbitmap, tmp - group->newsrc.xmin)) NSET1(newbitmap, tmp - first); else NSET0(newbitmap, tmp - first); } /* Mark earlier articles as read, updating num_unread */ if (first < group->newsrc.xmin) { NSETRNG0(newbitmap, 0L, group->newsrc.xmin - first - 1L); } { long i; for (i = group->newsrc.xmin; i < min; i++) { if (NTEST(newbitmap, i - first) != ART_READ) { NSET0(newbitmap, i - first); if (group->newsrc.num_unread) group->newsrc.num_unread--; } } } /* Mark high numbered articles as unread */ if (group->newsrc.xmin - first + group->newsrc.xbitlen < bitlen) { tmp = group->newsrc.xmin - first + group->newsrc.xbitlen; NSETRNG1(newbitmap, tmp, bitlen - 1); } free(group->newsrc.xbitmap); group->newsrc.xbitmap = newbitmap; #ifdef DEBUG_NEWSRC debug_print_comment("expand_bitmap: group->newsrc.bitlen != (group->max-group->min)+1 and need full copy"); #endif /* DEBUG_NEWSRC */ } else if (max != group->newsrc.xmax || first != group->newsrc.xmin) { t_bitmap *newbitmap; newbitmap = my_malloc(BITS_TO_BYTES(bitlen)); /* Copy over old bitmap */ assert((group->newsrc.xmin - first) / NBITS + BITS_TO_BYTES(group->newsrc.xbitlen) <= BITS_TO_BYTES(bitlen)); memcpy(newbitmap + (group->newsrc.xmin - first) / NBITS, group->newsrc.xbitmap, BITS_TO_BYTES(group->newsrc.xbitlen)); /* Mark earlier articles as read, updating num_unread */ if (first < group->newsrc.xmin) { NSETRNG0(newbitmap, 0L, group->newsrc.xmin - first - 1L); } { long i; for (i = group->newsrc.xmin; i < min; i++) { if (NTEST(newbitmap, i - first) != ART_READ) { NSET0(newbitmap, i - first); if (group->newsrc.num_unread) group->newsrc.num_unread--; } } } /* Mark high numbered articles as unread */ if (group->newsrc.xmin - first + group->newsrc.xbitlen < bitlen) { tmp = group->newsrc.xmin - first + group->newsrc.xbitlen; NSETRNG1(newbitmap, tmp, bitlen - 1); } free(group->newsrc.xbitmap); group->newsrc.xbitmap = newbitmap; #ifdef DEBUG_NEWSRC debug_print_comment("expand_bitmap: group->newsrc.bitlen != (group->max-group->min)+1"); #endif /* DEBUG_NEWSRC */ } group->newsrc.xmin = first; if (group->newsrc.xmax < max) group->newsrc.num_unread += max - group->newsrc.xmax; group->newsrc.xmax = max; group->newsrc.xbitlen = bitlen; group->newsrc.present = TRUE; }
bool FileListTransfer::DecodeFile(Packet *packet) { unsigned char *decompressedFileData; char fileName[512]; unsigned char context; unsigned fileIndex, fileLength, compressedLength; unsigned bitLength; unsigned len; unsigned short setID; RakNet::BitStream inBitStream(packet->data, packet->length, false); inBitStream.IgnoreBits(8); inBitStream.Read(context); inBitStream.Read(setID); FileListReceiver *fileListReceiver; if (fileListReceivers.Has(setID)==false) { #ifdef _DEBUG assert(0); #endif return false; } fileListReceiver=fileListReceivers.Get(setID); if (fileListReceiver->allowedSender!=packet->playerId) { #ifdef _DEBUG assert(0); #endif return false; } #ifdef _DEBUG assert(fileListReceiver->gotSetHeader==true); #endif inBitStream.ReadCompressed(fileIndex); inBitStream.ReadCompressed(fileLength); if (fileListReceiver->isCompressed) { inBitStream.ReadCompressed(bitLength); compressedLength=BITS_TO_BYTES(bitLength); } if (stringCompressor->DecodeString(fileName, 512, &inBitStream)==false) { #ifdef _DEBUG assert(0); #endif return false; } decompressedFileData = new unsigned char [fileLength]; if (fileListReceiver->isCompressed) { len=fileListReceiver->tree.DecodeArray(&inBitStream, bitLength, fileLength, decompressedFileData); if (len!=fileLength) { #ifdef _DEBUG assert(0); #endif delete [] decompressedFileData; return false; } } else inBitStream.Read((char*)decompressedFileData, fileLength); // User callback for this file. fileListReceiver->downloadHandler->OnFile(fileIndex, fileName, (char*)decompressedFileData, compressedLength, fileLength, setID, fileListReceiver->setCount, fileListReceiver->setTotalCompressedTransmissionLength, fileListReceiver->setTotalFinalLength, context); delete [] decompressedFileData; // If this set is done, free the memory for it. if (fileListReceiver->setCount==fileIndex+1) { if (fileListReceiver->deleteDownloadHandler) delete fileListReceiver->downloadHandler; delete fileListReceiver; fileListReceivers.Delete(setID); } return true; }
/* * Parse the newsrc sequence for the specified group */ static void parse_bitmap_seq( struct t_group *group, char *seq) { char *ptr; int sum = 0; long low = 0L; long high = 0L; long min, max; t_bool gotseq = FALSE; /* * Skip possible non-numeric prefix */ ptr = seq; while (ptr && *ptr && (*ptr < '0' || *ptr > '9')) ptr++; #ifdef DEBUG_NEWSRC { char buf[NEWSRC_LINE]; sprintf(buf, "Parsing [%s%c %.*s]", group->name, SUB_CHAR(group->subscribed), (int) (NEWSRC_LINE - strlen(group->name) - 20), ptr); debug_print_comment(buf); debug_print_bitmap(group, NULL); } #endif /* DEBUG_NEWSRC */ if (ptr) { gotseq = TRUE; ptr = parse_get_seq(ptr, &low, &high); if (high < group->xmin - 1) high = group->xmin - 1; min = ((low <= 1) ? (high + 1) : 1); if (group->xmin > min) min = group->xmin; if (group->xmax > high) max = group->xmax; else max = high; /* trust newsrc's max */ FreeAndNull(group->newsrc.xbitmap); group->newsrc.xmax = max; group->newsrc.xmin = min; group->newsrc.xbitlen = (max - min) + 1; if (group->newsrc.xbitlen > 0) { group->newsrc.xbitmap = my_malloc(BITS_TO_BYTES(group->newsrc.xbitlen)); NSETRNG1(group->newsrc.xbitmap, 0L, group->newsrc.xbitlen - 1L); } if (min <= high) { if (low > min) sum = low - min; else low = min; NSETRNG0(group->newsrc.xbitmap, low - min, high - min); } /* * Pick up any additional articles/ranges after the first */ while (*ptr) ptr = parse_subseq(group, ptr, &low, &high, &sum); } else { FreeAndNull(group->newsrc.xbitmap); group->newsrc.xmax = group->xmax; if (group->xmin > 0) group->newsrc.xmin = group->xmin; else group->newsrc.xmin = 1; group->newsrc.xbitlen = (group->newsrc.xmax - group->newsrc.xmin) + 1; if (group->newsrc.xbitlen > 0) { group->newsrc.xbitmap = my_malloc(BITS_TO_BYTES(group->newsrc.xbitlen)); NSETRNG1(group->newsrc.xbitmap, 0L, group->newsrc.xbitlen - 1L); } /* wait_message(2, "BITMAP Grp=[%s] MinMax=[%ld-%ld] Len=[%ld]\n", group->name, group->xmin, group->xmax, group->newsrc.xbitlen); */ } group->newsrc.present = TRUE; if (gotseq) { if (group->newsrc.xmax > high) sum += group->newsrc.xmax - high; } else sum = (int) ((group->count >= 0) ? group->count : ((group->newsrc.xmax - group->newsrc.xmin) + 1)); group->newsrc.num_unread = sum; #ifdef DEBUG_NEWSRC debug_print_bitmap(group, NULL); #endif /* DEBUG_NEWSRC */ }
void write_image_bitmap(int* ret, file_system_info fs_info, image_options img_opt, unsigned long* bitmap, cmd_opt* opt) { int i, debug = opt->debug; switch(img_opt.bitmap_mode) { case BM_BIT: { if (write_all(ret, (char*)bitmap, BITS_TO_BYTES(fs_info.totalblock), opt) == -1) log_mesg(0, 1, 1, debug, "write bitmap to image error: %s\n", strerror(errno)); break; } case BM_BYTE: { char bbuffer[16384]; for (i = 0; i < fs_info.totalblock; ++i) { bbuffer[i % sizeof(bbuffer)] = pc_test_bit(i, bitmap); if (i % sizeof(bbuffer) == sizeof(bbuffer) - 1 || i == fs_info.totalblock - 1) { if (write_all(ret, bbuffer, 1 + (i % sizeof(bbuffer)), opt) == -1) log_mesg(0, 1, 1, debug, "write bitmap to image error: %s\n", strerror(errno)); } } break; } case BM_NONE: { // All blocks MUST be present if (fs_info.usedblocks != fs_info.totalblock) log_mesg(0, 1, 1, debug, "ERROR: used blocks count does not match total blocks count\n"); break; } default: log_mesg(0, 1, 1, debug, "ERROR: unknown bitmap mode [%d]\n", img_opt.bitmap_mode); break; } if (img_opt.bitmap_mode != BM_NONE) { switch (img_opt.image_version) { case 0x0001: if (write_all(ret, BIT_MAGIC, BIT_MAGIC_SIZE, opt) != BIT_MAGIC_SIZE) log_mesg(0, 1, 1, debug, "write bitmap to image error: %s\n", strerror(errno)); break; case 0x0002: { uint32_t crc; init_crc32(&crc); crc = crc32(crc, bitmap, BITS_TO_BYTES(fs_info.totalblock)); if (write_all(ret, (char*)&crc, sizeof(crc), opt) != sizeof(crc)) log_mesg(0, 1, 1, debug, "write bitmap to image error: %s\n", strerror(errno)); break; } default: log_mesg(0, 1, 1, debug, "image_version is not set or write_image_bitmap() must to be updated [%d]\n", img_opt.image_version); break; } } }
/* * Parse a subsection of the newsrc sequencer ie., 1-34,23-90,93,97-99 * would parse the sequence if called in a loop in the following way: * 1st call would parse 1-34 and return 23-90,93,97-99 * 2nd call would parse 23-90 and return 93,97-99 * 3rd call would parse 93 and return 97-99 * 4th call would parse 97-99 and return NULL */ static char * parse_subseq( struct t_group *group, char *seq, long *low, long *high, int *sum) { long bitmin; long bitmax; long last_high = *high; seq = parse_get_seq(seq, low, high); /* * Bitmap index */ bitmin = *low - group->newsrc.xmin; /* * check that seq is not out of order */ if (*low > last_high) *sum += (*low - last_high) - 1; if (*high == *low) { if (bitmin >= 0) { if (*high > group->newsrc.xmax) { /* We trust .newsrc's max. */ long bitlen; t_bitmap *newbitmap; group->newsrc.xmax = *high; bitlen = group->newsrc.xmax - group->newsrc.xmin + 1; newbitmap = my_malloc(BITS_TO_BYTES(bitlen)); /* Copy over old bitmap */ memcpy(newbitmap, group->newsrc.xbitmap, BITS_TO_BYTES(group->newsrc.xbitlen)); /* Mark high numbered articles as unread */ NSETRNG1(newbitmap, group->newsrc.xbitlen, bitlen - 1); free(group->newsrc.xbitmap); group->newsrc.xbitmap = newbitmap; group->newsrc.xbitlen = bitlen; } NSET0(group->newsrc.xbitmap, bitmin); } } else if ((*low < *high) && (*high >= group->newsrc.xmin)) { /* * Restrict the range to min..max */ if (bitmin < 0) bitmin = 0; bitmax = *high; if (bitmax > group->newsrc.xmax) { /* We trust .newsrc's max. */ long bitlen; t_bitmap *newbitmap; group->newsrc.xmax = bitmax; bitlen = group->newsrc.xmax - group->newsrc.xmin + 1; newbitmap = my_malloc(BITS_TO_BYTES(bitlen)); /* Copy over old bitmap */ memcpy(newbitmap, group->newsrc.xbitmap, BITS_TO_BYTES(group->newsrc.xbitlen)); /* Mark high numbered articles as unread */ NSETRNG1(newbitmap, group->newsrc.xbitlen, bitlen - 1); free(group->newsrc.xbitmap); group->newsrc.xbitmap = newbitmap; group->newsrc.xbitlen = bitlen; } bitmax -= group->newsrc.xmin; /* * Fill in the whole range as read */ NSETRNG0(group->newsrc.xbitmap, bitmin, bitmax); } return seq; }
/* This functions codes all ixeme occurrences in a segment in the correct * order. The catch is that instead of using global ixeme IDs, we use a * minimal local set of IDs, namely integers [1..|S|] for |S| individual * ixemes. Mapping between the IDs is implictely saved in the ascending * order of ixeme IDs, obtainable from the forward index. */ void possect_add(const Pvoid_t tokens) { static uint *offsets; //static uint offsets_len; static char *encode_buf; //static uint buf_len; if (!offsets){ offsets = xmalloc(segment_size * sizeof(uint)); encode_buf = xmalloc(segment_size * 8); memset(encode_buf, 0, segment_size * 8); } memset(offsets, 0, segment_size * sizeof(uint)); //ENSURE_IBLOCK Word_t max = 0; JLC(max, tokens, 0, -1); /* write TOC entry */ toc_e toc; toc.offs = ftello64(data_f); toc.val = max; fwrite(&toc, sizeof(toc_e), 1, toc_f); /* write token list */ uint max_pos = encode_tokens(tokens); /* if (segment_size > offsets_len){ free(offsets); offsets_len = segment_size; offsets = xmalloc(offsets_len * sizeof(uint)); } memset(offsets, 0, offsets_len * sizeof(uint)); */ /* estimate rice_f */ u32 rice_f, offs = 0; if (max) rice_f = estimate_rice_f((u32*)&max, 1); else rice_f = 2; /* allocate bits to positions */ Word_t *ptr; //uint max_pos = 0; int i, j, c = 0; Word_t xid = 0; JLF(ptr, tokens, xid); while (ptr){ offs = 0; rice_write(NULL, &offs, ++c, rice_f); const growing_glist *g = (const growing_glist*)*ptr; for (i = 0; i < g->lst.len; i++){ offsets[g->lst.lst[i] - 1] = offs; if (g->lst.lst[i] > max_pos) max_pos = g->lst.lst[i]; } JLN(ptr, tokens, xid); } /* compute bit offset for each position */ offs = 0; elias_gamma_write(NULL, &offs, max_pos + 1); rice_write(NULL, &offs, rice_f, 2); for (i = 0; i < max_pos; i++){ uint tmp = offsets[i]; if (!tmp) dub_die("A hole in poslist at %u / %u!", i, max_pos); offsets[i] = offs; offs += tmp; } u32 endpos = offs; //u32 total_bits = offs; //elias_gamma_write(NULL, &offs, total_bits); //rice_write(NULL, &offs, 0, rice_f); u32 total_bytes = BITS_TO_BYTES(offs); if (total_bytes > segment_size * 8) dub_die("Pos buffer too small! %u > %u.", total_bytes, segment_size * 8); /* if (total_bytes > buf_len){ free(encode_buf); buf_len = total_bytes; encode_buf = xmalloc(buf_len + 4); memset(encode_buf, 0, buf_len + 4); } */ /* write codes */ offs = 0; elias_gamma_write(encode_buf, &offs, max_pos + 1); rice_write(encode_buf, &offs, rice_f, 2); //elias_gamma_write(encode_buf, &offs, total_bits); xid = c = j = 0; JLF(ptr, tokens, xid); while (ptr){ ++c; growing_glist *g = (growing_glist*)*ptr; for (i = 0; i < g->lst.len; i++){ //u32 d = offsets[g->lst.lst[i] - 1]; //dub_msg("OFFS %u VAL %u", d, c); rice_write(encode_buf, &offsets[g->lst.lst[i] - 1], c, rice_f); //u32 dd = rice_read(encode_buf, &d, rice_f); //if (c != dd) // dub_die("POKS! %u, %u != %u", key, dd, c); ++j; } free(g); JLN(ptr, tokens, xid); } //rice_write(encode_buf, &endpos, 0, rice_f); fwrite(encode_buf, total_bytes, 1, data_f); memset(encode_buf, 0, total_bytes); }
int main(int argc, char *argv[]) { if(argc != 2) { printf("Usage: xsvfplayer <filename>\n"); return 1; } if(NULL == (file = fopen(argv[1], "r"))) { printf("Cannot open file.\n"); return 1; } fseek(file, 0, SEEK_END); filesize = ftell(file); rewind(file); if(NULL == (xsvfprog = xsvfprog_open())) { printf("Cannot connect to XSVF player.\n"); return 1; } if(SUCCESS != xsvfprog_init(xsvfprog)) { printf("Initialization of XSVF player failed.\n"); xsvfprog_prgend(xsvfprog); return 1; } #ifdef DEBUG debugfile = fopen("debug.xsvf", "w"); #endif printf("Programming..."); while(!feof(file) && !quit) { bufsize = 0; /* get command */ file2buf(1); #ifdef DEBUG printf("instr 0x%02x: ", buf[0]); #endif /* read additional command parameters */ switch(buf[0]) { case XCOMPLETE: /* quit if XCOMPLETE command reached */ quit = 1; break; case XREPEAT: case XSTATE: case XENDIR: case XENDDR: /* these commands need one additional byte */ file2buf(1); #ifdef DEBUG printf("par = %d, ", buf[1]); #endif break; case XRUNTEST: /* this command needs four additional bytes */ file2buf(4); #ifdef DEBUG printf("delay = %d us, ", ntohl(*((long*) &buf[1]))); #endif break; case XTDOMASK: case XSDR: case XSDRB: case XSDRC: case XSDRE: /* these commands need drSize additional bits */ file2buf(BITS_TO_BYTES(drSize)); break; case XSDRTDO: case XSDRTDOB: case XSDRTDOC: case XSDRTDOE: /* these commands need 2x drSize additional bits */ file2buf(2 * BITS_TO_BYTES(drSize)); break; case XSDRSIZE: file2buf(4); drSize = ntohl(*((long*) &buf[1])); #ifdef DEBUG printf("drSize = %d, ", drSize); #endif if (BITS_TO_BYTES(drSize) > MAX_BITVEC_BYTES) { exit_err("\nData Register too long.\n"); } break; case XSIR: file2buf(1); irSize = *((unsigned char*) &buf[1]); #ifdef DEBUG printf("irSize = %d, ", irSize); #endif if (BITS_TO_BYTES(irSize) > MAX_BITVEC_BYTES) { exit_err("\nInstruction Register too long.\n"); } file2buf(BITS_TO_BYTES(irSize)); break; case XSIR2: file2buf(2); irSize = ntohs(*((short*) &buf[1])); #ifdef DEBUG printf("irSize = %d, ", irSize); #endif if (BITS_TO_BYTES(irSize) > MAX_BITVEC_BYTES) { exit_err("\nInstruction Register too long.\n"); } file2buf(BITS_TO_BYTES(irSize)); break; case XSETSDRMASKS: file2buf(2 * BITS_TO_BYTES(drSize)); drSize2 = BitStringOnes(drSize, &buf[1 + BITS_TO_BYTES(drSize)]); #ifdef DEBUG printf("drSize2 = %d, ", drSize2); #endif if (BITS_TO_BYTES(drSize2) > MAX_BITVEC_BYTES) { exit_err("\nData Register2 too long.\n"); } break; case XSDRINC: file2buf(BITS_TO_BYTES(drSize) + 1); int num = *((unsigned char*) &buf[1 + BITS_TO_BYTES(drSize)]); file2buf(num * BITS_TO_BYTES(drSize2)); break; case XCOMMENT: do { ch = fgetc(file); } while(ch != 0 && ch != EOF); /* we don't send comments to the programmer... */ continue; break; default: exit_err("\nIllegal XSVF command.\n"); break; } #ifdef DEBUG printf("%d bytes long\n", bufsize); fwrite(buf, 1, bufsize, debugfile); #endif ret = xsvfprog_exec(xsvfprog, buf, bufsize); #ifdef DEBUG printf("%d\n", ret); #endif switch(ret) { case 0: /* success, do nothing, just go on */ break; case UNKNOWN_COMMAND: exit_err("\nProgramming error: Unknown command.\n"); break; case XE_TDOMISMATCH: exit_err("\nProgramming error: Captured TDO value differs from expected TDO value.\n"); break; case XE_ILLEGALCMD: exit_err("\nProgramming error: Illegal XSVF command.\n"); break; case XE_ILLEGALSTATE: exit_err("\nProgramming error: Illegal TAP state.\n"); break; case XE_DATAOVERFLOW: exit_err("\nProgramming error: Bit string overflow.\n"); break; case XE_DATAUNDERFLOW: exit_err("\nProgramming error: End of command buffer reached expecting more data.\n"); break; default: exit_err("\nUnknown programming error.\n"); break; } filepos += bufsize; printf("\rProgramming... %3u%%", 100*filepos/filesize); fflush(stdout); } xsvfprog_prgend(xsvfprog); printf("\nDone.\n"); fclose(file); #ifdef DEBUG fclose(debugfile); #endif xsvfprog_close(xsvfprog); }