Store paths of 1's and 0's from root to leaf of a tree (Huffman coding) - c

I built a tree to be used for Huffman compression. I want to traverse this tree from root to leaf for all leaves. Along these traversals, I would like to store a 0 if the left path was taken and a 1 if the right path was taken. My code works for the leftmost leaf, but when it should store the path of its sibling, it only goes back to the parent node instead of the root node and then goes to the right and stores only a 1 instead of 01.
tree
132 void printArr(){
133 int i;
134 for(i=0; i<top; i++){
135 printf("%d\n", arr[i]);
136 }
137 printf("\n");
138 }
139
140 void storeCode(Node *rootNode){
141
142 if(rootNode->left){
143 arr[top] = 0;
144 top += 1;
145 storeCode(rootNode->left);
146 }
147 if(rootNode->right){
148 arr[top] = 1;
149 top += 1;
150 storeCode(rootNode->right);
151 }
152 if(isLeafNode(rootNode)){
153 arr[top] = rootNode->data;
154 top += 1;
155 return;
156 }
157
158 }
The result looks like this (the non 0 or 1 numbers are the characters):
0 0 103 1 111 1 0 0 115 1 32 1 0 0 101 1 104 1 0 112 1 114
The result should look like this:
0 0 103 0 1 111 1 0 0 115 1 0 1 32 1 1 0 0 101 1 1 0 1 104 1 1 1 0 112 1 1 1 1 114
How do I change my code so that the function traverses the tree from the root to a different leaf each time (until all leaves have been visited).

Related

MATLAB: Remove sub-arrays from a multidimensional array into an array of ones

I would like to construct a function
[B, ind] = extract_ones(A)
which removes some sub-arrays from a binary array A in arbitrary dimensions, such that the remaining array B is the largest possible array with only 1's, and I also would like to record in ind that where each of the 1's in B comes from.
Example 1
Assume A is a 2-D array as shown
A =
1 1 0 0 0 1
1 1 1 0 1 1
0 0 0 1 0 1
1 1 0 1 0 1
1 1 0 1 0 1
1 1 1 1 1 1
After removing A(3,:) and A(:,3:5), we have the output B
B =
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
which is the largest array with only ones by removing rows and columns of A.
As the fifteen 1's of B corresponds to
A(1,1) A(1,2) A(1,6)
A(2,1) A(2,2) A(2,6)
A(4,1) A(4,2) A(4,6)
A(5,1) A(5,2) A(5,6)
A(6,1) A(6,2) A(6,6)
respectively, or equivalently
A(1) A(7) A(31)
A(2) A(8) A(32)
A(4) A(10) A(34)
A(5) A(11) A(35)
A(6) A(12) A(36)
so, the output ind looks like (of course ind's shape does not matter):
ind = [1 2 4 5 6 7 8 10 11 12 31 32 34 35 36]
Example 2
If the input A is constructed by
A = ones(6,3,4,3);
A(2,2,2,2) = 0;
A(4,1,3,3) = 0;
A(1,1,4,2) = 0;
A(1,1,4,1) = 0;
Then, by deleting the minimum cuboids containing A(2,2,2,2), A(4,1,3,3), A(1,1,4,3) and A(1,1,4,1), i.e. after deleting these entries
A(2,:,:,:)
A(:,1,:,:)
Then the remaining array B will be composed by 1's only. And the ones in B corresponds to
A([1,3:6],2:3,1:4,1:3)
So, the output ind lists the subscripts transformed into indices, i.e.
ind = [7 9 10 11 12 13 15 16 17 18 25 27 28 29 30 31 33 34 35 36 43 45 46 47 48 49 51 52 53 54 61 63 64 65 66 67 69 70 71 72 79 81 82 83 84 85 87 88 89 90 97 99 100 101 102 103 105 106 107 108 115 117 118 119 120 121 123 124 125 126 133 135 136 137 138 139 141 142 143 144 151 153 154 155 156 157 159 160 161 162 169 171 172 173 174 175 177 178 179 180 187 189 190 191 192 193 195 196 197 198 205 207 208 209 210 211 213 214 215 216]
As the array needed to be processed as above is in 8-D, and it should be processed more than once, so can anyone give me opinions on how to composing the program doing this task fast?
My work so far [Added at 2 am (GMT-4), 2nd Aug 2017]
My idea was that I delete the sub-arrays with the largest proportion of zero one by one. And here is my work so far:
Inds = reshape(1:numel(A),size(A)); % Keep track on which 1's survive.
cont = true;
while cont
sz = size(A);
zero_percentage = 0;
Test_location = [];
% This nested for loops are for determining which sub-array of A has the
% maximum proportion of zeros.
for J = 1 : ndims(A)
for K = 1 : sz(J)
% Location is in the form of (_,_,_,...,_)
% where the J-th blank is K, the other blanks are colons.
Location = strcat('(',repmat(':,',1,(J-1)),int2str(K),repmat(',:',1,(ndims(A)-J)),')');
Test_array = eval(strcat('A',Location,';'));
N = numel(Test_array);
while numel(Test_array) ~= 1
Test_array = sum(Test_array);
end
test_zero_percentage = 1 - (Test_array/N);
if test_zero_percentage > zero_percentage
zero_percentage = test_zero_percentage;
Test_location = Location;
end
end
end
% Delete the array with maximum proportion of zeros
eval(strcat('A',Test_location,'= [];'))
eval(strcat('Inds',Test_location,'= [];'))
% Determine if there are still zeros in A. If there are, continue the while loop.
cont = A;
while numel(cont) ~= 1
cont = prod(cont);
end
cont = ~logical(cont);
end
But I encountered two problems:
1) It may be not efficient to check all arrays in all sub-dimensions one-by-one.
2) The result does not contain the most number of rectangular ones. for example, I tested my work using a 2-dimensional binary array A
A =
0 0 0 1 1 0
0 1 1 0 1 1
1 0 1 1 1 1
1 0 0 1 1 1
0 1 1 0 1 1
0 1 0 0 1 1
1 0 0 0 1 1
1 0 0 0 0 0
It should return me the result as
B =
1 1
1 1
1 1
1 1
1 1
1 1
Inds =
34 42
35 43
36 44
37 45
38 46
39 47
But, instead, the code returned me this:
B =
1 1 1
1 1 1
1 1 1
Inds =
10 34 42
13 37 45
14 38 46
*My work so far 2 [Added at 12noon (GMT-4), 2nd Aug 2017]
Here is my current amendment. This may not provide the best result.
This may give a fairly OK approximation to the problem, and this does not give empty Inds. But I am still hoping that there is a better solution.
function [B, Inds] = Finding_ones(A)
Inds = reshape(1:numel(A),size(A)); % Keep track on which 1's survive.
sz0 = size(A);
cont = true;
while cont
sz = size(A);
zero_percentage = 0;
Test_location = [];
% This nested for loops are for determining which sub-array of A has the
% maximum proportion of zeros.
for J = 1 : ndims(A)
for K = 1 : sz(J)
% Location is in the form of (_,_,_,...,_)
% where the J-th blank is K, the other blanks are colons.
Location = strcat('(',repmat(':,',1,(J-1)),int2str(K),repmat(',:',1,(ndims(A)-J)),')');
Test_array = eval(strcat('A',Location,';'));
N = numel(Test_array);
Test_array = sum(Test_array(:));
test_zero_percentage = 1 - (Test_array/N);
if test_zero_percentage > zero_percentage
eval(strcat('Testfornumel = numel(A',Location,');'))
if Testfornumel < numel(A) % Preventing the A from being empty
zero_percentage = test_zero_percentage;
Test_location = Location;
end
end
end
end
% Delete the array with maximum proportion of zeros
eval(strcat('A',Test_location,'= [];'))
eval(strcat('Inds',Test_location,'= [];'))
% Determine if there are still zeros in A. If there are, continue the while loop.
cont = A;
while numel(cont) ~= 1
cont = prod(cont);
end
cont = ~logical(cont);
end
B = A;
% command = 'i1, i2, ... ,in'
% here, n is the number of dimansion of A.
command = 'i1';
for J = 2 : length(sz0)
command = strcat(command,',i',int2str(J));
end
Inds = reshape(Inds,numel(Inds),1); %#ok<NASGU>
eval(strcat('[',command,'] = ind2sub(sz0,Inds);'))
% Reform Inds into a 2-D matrix, which each column indicate the location of
% the 1 originated from A.
Inds = squeeze(eval(strcat('[',command,']')));
Inds = reshape(Inds',length(sz0),numel(Inds)/length(sz0));
end
It seems a difficult problem to solve, since the order of deletion can change a lot in the final result. If in your first example you start with deleting all the columns that contain a 0, you don't end up with the desired result.
The code below removes the row or column with the most zeros and keeps going until it's only ones. It keeps track of the rows and columns that are deleted to find the indexes of the remaining ones.
function [B,ind] = extract_ones( A )
if ~islogical(A),A=(A==1);end
if ~any(A(:)),B=[];ind=[];return,end
B=A;cdel=[];rdel=[];
while ~all(B(:))
[I,J] = ind2sub(size(B),find(B==0));
ih=histcounts(I,[0.5:1:size(B,1)+0.5]); %zero's in rows
jh=histcounts(J,[0.5:1:size(B,2)+0.5]); %zero's in columns
if max(ih)>max(jh)
idxr=find(ih==max(ih),1,'first');
B(idxr,:)=[];
%store deletion
rdel(end+1)=idxr+sum(rdel<=idxr);
elseif max(ih)==max(jh)
idxr=find(ih==max(ih),1,'first');
idxc=find(jh==max(jh),1,'first');
B(idxr,:)=[];
B(:,idxc)=[];
%store deletions
rdel(end+1)=idxr+sum(rdel<=idxr);
cdel(end+1)=idxc+sum(cdel<=idxc);
else
idxc=find(jh==max(jh),1,'first');
B(:,idxc)=[];
%store deletions
cdel(end+1)=idxc+sum(cdel<=idxc);
end
end
A(rdel,:)=0;
A(:,cdel)=0;
ind=find(A);
Second try: Start with a seed point and try to grow the matrix in all dimensions. The result is the start and finish point in the matrix.
function [ res ] = seed_grow( A )
if ~islogical(A),A=(A==1);end
if ~any(A(:)),res={};end
go = true;
dims=size(A);
ind = cell([1 length(dims)]); %cell to store find results
seeds=A;maxmat=0;
while go %main loop to remove all posible seeds
[ind{:}]=find(seeds,1,'first');
S = [ind{:}]; %the seed
St = [ind{:}]; %the end of the seed
go2=true;
val_dims=1:length(dims);
while go2 %loop to grow each dimension
D=1;
while D<=length(val_dims) %add one to each dimension
St(val_dims(D))=St(val_dims(D))+1;
I={};
for ct = 1:length(S),I{ct}=S(ct):St(ct);end %generate indices
if St(val_dims(D))>dims(val_dims(D))
res=false;%outside matrix
else
res=A(I{:});
end
if ~all(res(:)) %invalid addition to dimension
St(val_dims(D))=St(val_dims(D))-1; %undo
val_dims(D)=[]; D=D-1; %do not try again
if isempty(val_dims),go2=false;end %end of growth
end
D=D+1;
end
end
%evaluate the result
mat = prod((St+1)-S); %size of matrix
if mat>maxmat
res={S,St};
maxmat=mat;
end
%tried to expand, now remove seed option
for ct = 1:length(S),I{ct}=S(ct):St(ct);end %generate indices
seeds(I{:})=0;
if ~any(seeds),go=0;end
end
end
I tested it using your matrix:
A = [0 0 0 1 1 0
0 1 1 0 1 1
1 0 1 1 1 1
1 0 0 1 1 1
0 1 1 0 1 1
0 1 0 0 1 1
1 0 0 0 1 1
1 0 0 0 0 0];
[ res ] = seed_grow( A );
for ct = 1:length(res),I{ct}=res{1}(ct):res{2}(ct);end %generate indices
B=A(I{:});
idx = reshape(1:numel(A),size(A));
idx = idx(I{:});
And got the desired result:
B =
1 1
1 1
1 1
1 1
1 1
1 1
idx =
34 42
35 43
36 44
37 45
38 46
39 47

Working with PPM image as an int *img

I've been trying to implement the MSF using a grayscale PPM image and a template. I need to declare the image as "*int" img instead of unsigned char img. But when I compute the zero-mean center at the template, I get values that doesn't make any sense. I tried unsigned char and it gives the right pixel values before the zero-mean center and wrong after because 'unsigned char' does't have enough 'space' and doesn't accept negative values but at least it's consistent values. I know it's a silly mistake but I'm stuck on it. Could anyone help me on how could I implement it using int*? Thanks
Below is part of my code and both results
FILE *fpt1, *fpt2, *fpt3;
int *img, *gt, *int;
char header[320], header2[320];
int COLS, ROWS, BYTES, COLS2, ROWS2, BYTES2, i, len;
int r , c, count, sum;
/*Read template*/
fpt2 = fopen("parenthood_e_template.ppm", "r");
if (fpt2 == NULL){
printf("Unable to open template of parenthood.ppm for reading\n");
exit(0);
}
fscanf(fpt2,"%s %d %d %d\n", header2, &COLS2, &ROWS2, &BYTES2);
if (strcmp(header2, "P5") != 0 || BYTES2 != 255){
printf("Not a template for parenthood.ppm\n");
exit(0);
}
/*Allocate memory for template*/
temp = (int*) calloc (COLS2*ROWS2, sizeof(int));
/* Copy template into memory*/
header2[0] = fgetc(fpt2);
fread(temp,1,COLS2*ROWS2,fpt2);
fclose(fpt2);
/* Matched Spatial-Filter */
/* zero-mean the template*/
sum=0;
count=0;
for (r=0; r<ROWS2; r++) {
for (c=0; c<COLS2; c++) {
sum += temp[r*COLS2+c];
printf("temp[%d]= %d\n", count, temp[r*COLS2+c]);
count += 1;
}
}
sum = sum/126;
The result for char*
temp[0]= 199
temp[1]= 196
temp[2]= 199
temp[3]= 198
temp[4]= 198
temp[5]= 199
temp[6]= 199
temp[7]= 202
temp[8]= 197
temp[9]= 196
temp[10]= 195
temp[11]= 198
temp[12]= 200
temp[13]= 197
temp[14]= 199
temp[15]= 199
temp[16]= 198
temp[17]= 195
temp[18]= 196
temp[19]= 196
temp[20]= 199
temp[21]= 197
temp[22]= 198
temp[23]= 196
temp[24]= 196
temp[25]= 193
temp[26]= 194
temp[27]= 195
temp[28]= 193
temp[29]= 155
temp[30]= 133
temp[31]= 150
temp[32]= 187
temp[33]= 196
temp[34]= 196
temp[35]= 195
temp[36]= 192
temp[37]= 109
temp[38]= 69
temp[39]= 105
temp[40]= 88
temp[41]= 78
temp[42]= 184
temp[43]= 194
temp[44]= 193
temp[45]= 145
temp[46]= 74
temp[47]= 177
temp[48]= 189
temp[49]= 186
temp[50]= 100
temp[51]= 105
temp[52]= 191
temp[53]= 191
temp[54]= 72
temp[55]= 139
temp[56]= 191
temp[57]= 192
temp[58]= 188
temp[59]= 168
temp[60]= 46
temp[61]= 183
temp[62]= 186
temp[63]= 43
temp[64]= 89
temp[65]= 110
temp[66]= 114
temp[67]= 114
temp[68]= 107
temp[69]= 37
temp[70]= 176
temp[71]= 191
temp[72]= 43
temp[73]= 126
temp[74]= 133
temp[75]= 133
temp[76]= 137
temp[77]= 129
temp[78]= 132
temp[79]= 187
temp[80]= 191
temp[81]= 52
temp[82]= 167
temp[83]= 188
temp[84]= 192
temp[85]= 195
temp[86]= 195
temp[87]= 195
temp[88]= 191
temp[89]= 189
temp[90]= 94
temp[91]= 108
temp[92]= 189
temp[93]= 193
temp[94]= 192
temp[95]= 191
temp[96]= 192
temp[97]= 192
temp[98]= 193
temp[99]= 173
temp[100]= 49
temp[101]= 141
temp[102]= 175
temp[103]= 177
temp[104]= 108
temp[105]= 125
temp[106]= 195
temp[107]= 199
temp[108]= 197
temp[109]= 163
temp[110]= 90
temp[111]= 70
temp[112]= 75
temp[113]= 109
temp[114]= 180
temp[115]= 191
temp[116]= 194
temp[117]= 197
temp[118]= 193
temp[119]= 192
temp[120]= 185
temp[121]= 188
temp[122]= 195
temp[123]= 196
temp[124]= 195
temp[125]= 0
C= 9 R= 14
temp = 35 mean=161
And the result for int*
temp[0]= -959986489
temp[1]= -892876858
temp[2]= -960248635
temp[3]= -943209016
temp[4]= -993737786
temp[5]= -993606201
temp[6]= -1010646588
temp[7]= -1769628735
temp[8]= -1010514757
temp[9]= 1766157760
temp[10]= -1028108712
temp[11]= -1320513087
temp[12]= 1768209085
temp[13]= -1958166593
temp[14]= -1464024897
temp[15]= 733656878
temp[16]= 1920101977
temp[17]= -1078975125
temp[18]= -2054848981
temp[19]= -1148943991
temp[20]= -1129892673
temp[21]= -1010580544
temp[22]= 1818148287
temp[23]= -1077886531
temp[24]= -1379811136
temp[25]= -1313895119
temp[26]= -943489684
temp[27]= 1180345285
temp[28]= -1078694581
temp[29]= -1061042750
temp[30]= -993805127
temp[31]= 195
temp[32]= 0
temp[33]= 0
temp[34]= 0
temp[35]= 0
temp[36]= 0
temp[37]= 0
temp[38]= 0
temp[39]= 0
temp[40]= 0
temp[41]= 0
temp[42]= 0
temp[43]= 0
temp[44]= 0
temp[45]= 0
temp[46]= 0
temp[47]= 0
temp[48]= 0
temp[49]= 0
temp[50]= 0
temp[51]= 0
temp[52]= 0
temp[53]= 0
temp[54]= 0
temp[55]= 0
temp[56]= 0
temp[57]= 0
temp[58]= 0
temp[59]= 0
temp[60]= 0
temp[61]= 0
temp[62]= 0
temp[63]= 0
temp[64]= 0
temp[65]= 0
temp[66]= 0
temp[67]= 0
temp[68]= 0
temp[69]= 0
temp[70]= 0
temp[71]= 0
temp[72]= 0
temp[73]= 0
temp[74]= 0
temp[75]= 0
temp[76]= 0
temp[77]= 0
temp[78]= 0
temp[79]= 0
temp[80]= 0
temp[81]= 0
temp[82]= 0
temp[83]= 0
temp[84]= 0
temp[85]= 0
temp[86]= 0
temp[87]= 0
temp[88]= 0
temp[89]= 0
temp[90]= 0
temp[91]= 0
temp[92]= 0
temp[93]= 0
temp[94]= 0
temp[95]= 0
temp[96]= 0
temp[97]= 0
temp[98]= 0
temp[99]= 0
temp[100]= 0
temp[101]= 0
temp[102]= 0
temp[103]= 0
temp[104]= 0
temp[105]= 0
temp[106]= 0
temp[107]= 0
temp[108]= 0
temp[109]= 0
temp[110]= 0
temp[111]= 0
temp[112]= 0
temp[113]= 0
temp[114]= 0
temp[115]= 0
temp[116]= 0
temp[117]= 0
temp[118]= 0
temp[119]= 0
temp[120]= 0
temp[121]= 0
temp[122]= 0
temp[123]= 0
temp[124]= 0
temp[125]= 0
C= 9 R= 14
temp = -8605725 mean=8605725

Finding Octet in a UDP data payload in C program

I am trying to collect UDP data payload information using C program by capturing the packet from port 6343. The code I am using is as follows:
#include<stdio.h> //For standard things
#include<stdlib.h> //malloc
#include<string.h> //memset
#include<netinet/ip_icmp.h> //Provides declarations for icmp header
#include<netinet/udp.h> //Provides declarations for udp header
#include<netinet/tcp.h> //Provides declarations for tcp header
#include<netinet/ip.h> //Provides declarations for ip header
#include<sys/socket.h>
#include<arpa/inet.h>
#include<net/ethernet.h>
#include<netinet/if_ether.h>
#define PORT 6343 // define the port to connect
#define ETH_P_IP 0x0800
void ProcessPacket(unsigned char*, int);
void print_ethernet_header(unsigned char*, int);
void print_ip_header(unsigned char* , int);
void print_udp_packet(unsigned char*, int);
void Dataint (unsigned char* , int);
void print(const int *, const int);
int sockt;
int i,j;
struct sockaddr_in source,dest;
const MAX_HEADER_SIZE = 256; /* The maximum sampled header size. */
struct sampled_header {
header_protocol protocol; /* Format of sampled header */
unsigned int frame_length; /* Original length of packet before
sampling */
opaque header{MAX_HEADER_SIZE}; /* Header bytes */
}
/* Packet IP version 4 data */
struct sampled_ipv4 {
unsigned int length; /* The length of the IP packet excluding
lower layer encapsulations */
unsigned int protocol; /* IP Protocol type
(for example, TCP = 6, UDP = 17) */
ip_v4 src_ip; /* Source IP Address */
ip_v4 dst_ip; /* Destination IP Address */
unsigned int src_port; /* TCP/UDP source port number or
equivalent */
unsigned int dst_port; /* TCP/UDP destination port number or
equivalent */
unsigned int tcp_flags; /* TCP flags */
unsigned int tos; /* IP type of service */
}
/* Packet IP version 6 data */
struct sampled_ipv6 {
unsigned int length; /* The length of the IP packet excluding
lower layer encapsulations */
unsigned int protocol; /* IP next header
(for example, TCP = 6, UDP = 17) */
ip_v6 src_ip; /* Source IP Address */
ip_v6 dst_ip; /* Destination IP Address */
unsigned int src_port; /* TCP/UDP source port number or
equivalent */
unsigned int dst_port; /* TCP/UDP destination port number or
equivalent */
unsigned int tcp_flags; /* TCP flags */
unsigned int priority; /* IP priority */
}
struct extended_switch {
unsigned int src_vlan; /* The 802.1Q VLAN id of incoming frame */
unsigned int src_priority; /* The 802.1p priority of incoming
frame */
unsigned int dst_vlan; /* The 802.1Q VLAN id of outgoing frame */
unsigned int dst_priority; /* The 802.1p priority of outgoing
frame */
}
int main()
{
int saddr_size,data_size, datasize;
struct sockaddr_in saddr;
struct sockaddr_in daddr;
struct in_addr addr;
int protocol=17;
unsigned char* buffer = (unsigned char *)malloc(65535); // Its Big ! Malloc allocates a block of size bytes of memory,returning a pointer to the begining of the block
//Create a socket
sockt = socket(AF_INET ,SOCK_DGRAM ,IPPROTO_UDP);
if(sockt < 0)
{
printf("Socket Error\n");
return 1;
}
memset((char *)&daddr,0,sizeof(daddr));
//prepare the sockaddr_in structure
saddr.sin_family = AF_INET;
daddr.sin_family = AF_INET;
daddr.sin_addr.s_addr = htonl(INADDR_ANY);
daddr.sin_port = htons(PORT);
saddr.sin_port = htons(PORT);
//Bind the socket
if(bind(sockt,(struct sockaddr *)&daddr, sizeof(daddr))<0)
{
printf("bind failed");
return 1;
}
printf("bind done");
while(1)
{
saddr_size = sizeof saddr;
printf(" waiting for data...\n");
//Receive a packet
datasize = recvfrom(sockt , buffer ,65535 , 0 , (struct sockaddr*) &saddr , (socklen_t*)&saddr_size);
data_size = recvfrom(sockt , buffer ,65535 , 0 , NULL , NULL);
if(data_size <0)
{
printf("Packets not recieved \n");
return 1;
}
printf("Packets arrived from %d \n",ntohs(daddr.sin_port));
printf("packet recieved : %lu bytes\n", datasize);
ProcessPacket(buffer , data_size);
}
close(sockt);
printf("Finished");
return 0;
}
void ProcessPacket(unsigned char* buffer, int len)
{
print_udp_packet(buffer , len);
}
void print_ethernet_header(unsigned char* buffer, int len)
{
struct ethhdr *eth = (struct ethhdr *)buffer;
printf("Ethernet Header\n");
printf("---------------------------------------\n");
printf("Ethernet Header Length : %u bytes \n",sizeof(eth));
printf("Destination MAC : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X \n", eth->h_dest[0] , eth->h_dest[1] , eth->h_dest[2] , eth->h_dest[3] , eth->h_dest[4] , eth->h_dest[5] );
printf("Source MAC : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X \n", eth->h_source[0] , eth->h_source[1] , eth->h_source[2] , eth->h_source[3] , eth->h_source[4] , eth->h_source[5] );
printf("Ethernet Type : %u \n",eth->h_proto);
printf("---------------------------------------\n");
}
void print_ip_header(unsigned char* buffer, int len)
{
//print_ethernet_header(buffer , len);
struct iphdr *iph = (struct iphdr *)(buffer + sizeof(struct ethhdr));
unsigned short iphdrlen = iph->ihl*4;
memset(&source,0,sizeof(source));
source.sin_addr.s_addr = iph ->saddr;
memset(&dest,0,sizeof(dest));
dest.sin_addr.s_addr = iph->daddr;
printf("IP Header\n");
printf("---------------------------------------\n");
printf("IP Length : %d\n", ntohs(iph->tot_len));
printf("Source IP : %s\n",inet_ntoa(source.sin_addr));
printf("Destination IP : %s\n",inet_ntoa(dest.sin_addr));
printf("Protocol : %d\n", iph->protocol);
printf("Type Of Service : %d\n",htons(iph->tos));
printf("---------------------------------------\n");
}
void print_udp_packet(unsigned char* buffer , int len)
{
struct sockaddr_in saddr;
struct sockaddr_in daddr;
unsigned short iphdrlen;
unsigned char* payload = (unsigned char *)malloc(1024);
struct iphdr *iph = (struct iphdr *)(buffer+ sizeof(struct ethhdr));
iphdrlen = iph->ihl*4;
struct udphdr *udph = (struct udphdr*)(buffer + sizeof(struct iphdr)+sizeof(struct ethhdr));
int header_size = sizeof(struct ethhdr) + iphdrlen + sizeof udph;
print_ip_header(buffer,len);
printf("UDP Header\n");
printf("---------------------------------------\n");
printf("UDP Length : %d\n", ntohs(udph->len));
//printf("UDP Length : %d\n", ntohs(sizeof (struct udphdr)));
printf("Source Port : %d\n ",ntohs(udph->source));
printf("Destination Port : %d\n ",ntohs(udph->dest));
printf("Source Port : %d\n ",ntohs(saddr.sin_port));
printf("Destination Port : %d\n ",ntohs(daddr.sin_port));
printf("---------------------------------------\n");
printf("Data Payload\n");
//PrintData(buffer + header_size , len - header_size);
Dataint(buffer ,len);
printf("--------------------------------------------\n");
}
void Dataint (unsigned char* buffer , int len)
{
int i,j;
i=0;
for(i=0 ; i <= len ; i++)
{
if( i!=0 && i%16==0) // prints every hex line with a space
{
printf(" ");
}
// prints entire data in integer
if(i%16==0)
printf(" "); // prints the first element of hex line
printf(" %d",(unsigned int)buffer[i]);
//print the last spaces
if( i==len-1)
{
for(j=0;j<16-i%16;j++)
printf(" ");
}
}
}
I have the payload converted to integer form as shown below:
0 0 0 5 0 0 0 1 147 188 192 6 0 0 0 0 0 50 170 143 37 107 3 154 0 0 0 6 0 0 0 1 0 0 0 208 1 30 136 36 0 0 0 29 0 0 1 0 236 205 212 188 0 22 44 215 0 0 0 29 0 0 0 40 0 0 0 2 0 0 0 1 0 0 0 144 0 0 0 1 0 0 5 238 0 0 0 4 0 0 0 128 240 146 28 72 194 0 0 14 12 48 199 199 8 0 69 0 5 220 65 28 64 0 47 6 24 125 193 104 215 69 147 188 192 24 0 80 142 152 237 55 211 205 114 104 162 142 128 16 0 54 188 178 0 0 1 1 8 10 139 71 198 30 37 2 188 177 205 144 135 164 154 194 155 33 30 238 48 113 112 179 62 180 223 221 169 24 234 48 163 41 188 139 148 98 130 255 16 229 123 58 202 165 56 101 14 217 132 108 10 156 47 29 77 156 220 141 202 248 196 75 240 252 232 27 19 140 52 187 0 0 3 233 0 0 0 16 0 0 0 3 0 0 0 2 0 0 0 2 255 255 255 255 0 0 0 1 0 0 0 208 1 30 136 37 0 0 0 29 0 0 1 0 236 205 214 47 0 22 44 215 0 0 0 29 0 0 0 40 0 0 0 2 0 0 0 1 0 0 0 144 0 0 0 1 0 0 5 238 0 0 0 4 0 0 0 128 240 146 28 72 194 0 0 14 12 48 199 199 8 0 69 0 5 220 65 243 64 0 47 6 23 166 193 104 215 69 147 188 192 24 0 80 142 152 237 60 147 229 114 104 162 142 128 16 0 54 13 151 0 0 1 1 8 10 139 71 198 66 37 2 188 213 16 243 209 241 120 208 124 252 85 108 101 62 10 255 21 98 62 58 136 127 106 62 238 76 85 231 227 224 70 62 31 217 151 211 47 106 246 111 160 87 164 114 43 83 45 230 197 131 18 49 110 159 251 162 207 148 178 31 212 40 81 190 0 0 3 233 0 0 0 16 0 0 0 3 0 0 0 2 0 0 0 2 255 255 255 255 0 0 0 1 0 0 0 148 1 30 136 38 0 0 0 29 0 0 1 0 236 205 214 158 0 22 44 215 0 0 0 0 0 0 0 29 0 0 0 2 0 0 0 1 0 0 0 84 0 0 0 1 0 0 0 70 0 0 0 4 0 0 0 68 0 14 12 48 199 199 240 146 28 72 194 0 8 0 69 0 0 52 28 175 64 0 63 6 50 146 147 188 192 24 193 104 215 69 142 152 0 80 114 104 162 142 237 62 109 231 128 16 36 63 51 129 0 0 1 1 8 10 37 2 188 231 139 71 198 66 0 0 0 0 3 233 0 0 0 16 255 255 255 255 0 0 0 0 0 0 0 3 255 255 255 255 0 0 0 1 0 0 0 208 1 30 136 39 0 0 0 29 0 0 1 0 236 205 215 173 0 22 44 215 0 0 0 29 0 0 0 40 0 0 0 2 0 0 0 1 0 0 0 144 0 0 0 1 0 0 5 238 0 0 0 4 0 0 0 128 240 146 28 72 194 0 0 14 12 48 199 199 8 0 69 0 5 220 67 10 64 0 47 6 22 143 193 104 215 69 147 188 192 24 0 80 142 152 237 66 188 223 114 104 162 142 128 16 0 54 185 33 0 0 1 1 8 10 139 71 198 102 37 2 188 248 226 4 177 86 140 52 15 181 49 144 230 162 19 81 72 179 190 46 196 123 24 85 38 153 175 213 96 59 3 73 194 138 211 35 187 143 148 46 200 190 255 249 6 223 220 57 180 2 123 223 184 204 149 28 127 218 240 134 94 247 236 103 0 0 3 233 0 0 0 16 0 0 0 3 0 0 0 2 0 0 0 2 255 255 255 255 0 0 0 1 0 0 0 208 1 30 136 40 0 0 0 29 0 0 1 0 236 205 216 48 0 22 44 215 0 0 0 29 0 0 0 40 0 0 0 2 0 0 0 1 0 0 0 144 0 0 0 1 0 0 5 238 0 0 0 4 0 0 0 128 240 146 28 72 194 0 0 14 12 48 199 199 8 0 69 0 5 220 67 144 64 0 47 6 22 9 193 104 215 69 147 188 192 24 0 80 142 152 237 69 173 223 114 104 162 142 128 16 0 54 47 172 0 0 1 1 8 10 139 71 198 102 37 2 188 249 253 49 241 16 12 100 96 130 25 195 170 251 218 202 149 6 45 216 81 206 145 254 7 147 240 20 103 185 112 138 115 50 158 226 156 204 78 113 98 240 114 65 240 51 253 252 102 174 242 80 12 50 241 179 148 204 90 200 196 66 118 137 0 0 3 233 0 0 0 16 0 0 0 3 0 0 0 2 0 0 0 2 255 255 255 255 0 0 0 1 0 0 0 148 1 30 136 41 0 0 0 29 0 0 1 0 236 205 217 14 0 22 44 215 0 0 0 29 0 0 0 25 0 0 0 2 0 0 0 1 0 0 0 84 0 0 0 1 0 0 0 70 0 0 0 4 0 0 0 68 240 146 28 72 194 0 0 14 12 48 199 199 8 0 69 0 0 52 174 239 0 0 48 6 219 72 216 58 210 78 147 188 194 70 1 187 179 154 222 83 63 174 28 240 175 235 128 16 5 91 120 31 0 0 1 1 8 10 94 165 224 71 49 84 232 65 0 0 0 0 3 233 0 0 0 16 0 0 0 3 0 0 0 2 0 0 0 14 255 255 255 255
This is a sflow data collected from a core switch.So I have to find the Ethernet, IPv4, IPv6,extended switch data from this payload and print them. Before that I need to find the octet position of each of these in the payload. can you advise me how should I find the octet position of each of them ?
Errors while using the structs in above code:
udps.c:25: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘ip_v4’
udps.c:26: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘ip_v6’
udps.c:33: error: two or more data types in declaration specifiers
udps.c:33: error: expected ‘)’ before ‘type’
udps.c:45: error: expected specifier-qualifier-list before ‘header_protocol’
udps.c:58: error: expected specifier-qualifier-list before ‘ip_v4’
udps.c:69: error: two or more data types in declaration specifiers
udps.c:74: error: expected specifier-qualifier-list before ‘ip_v6’
udps.c:87: error: two or more data types in declaration specifiers
udps.c:93: error: two or more data types in declaration specifiers
udps.c:93: error: two or more data types in declaration specifiers
udps.c:93: error: expected ‘)’ before ‘type’
udps.c:115: error: two or more data types in declaration specifiers
udps.c: In function ‘main’:
udps.c:131: error: incompatible types when returning type ‘int’ but ‘struct extended_switch’ was expected
udps.c:147: error: incompatible types when returning type ‘int’ but ‘struct extended_switch’ was expected
udps.c:163: error: incompatible types when returning type ‘int’ but ‘struct extended_switch’ was expected
udps.c:173: error: incompatible types when returning type ‘int’ but ‘struct extended_switch’ was expected
When use create a socket of type AF_INET / SOCK_DGRAM, the operating system processes the Ethernet, IP, and UDP headers and strips them off before passing them to you. What you see in buffer is what immediately follows the UDP header.
The fifth parameter to recvfrom gives you the source IP and source port of the incoming packet. If you want to see more than just that you need to use a packet capture library like libpcap.
Edit:
It seems that this data packet contains IP addresses as part of sflow data. You were trying to parse it as if it was a raw Ethernet frame. What you instead need to do is look at the sflow datagram definition and use that to figure out how the packet is laid out and parse accordingly. You don't need to use memcpy to do that, just use pointers to the relevant structs to point to the proper place in the buffer. This is the same basic technique you were using before, just with a different set of structs.
Edit 2:
It looks like we're way off on what the data looks like. I took the bytes from the packet listed above, read them into a buffer and sent it out in a UDP packet. I fired up Wireshark, which gave us this:
So the packet contains:
The sflow version, 32-bit (5)
an 32 bit int (value=1)
a struct sample_datagram_v5
the number of samples (32-bit int, value=6)
six samples
The first sample contains:
The sample type as a data_format (in this case a flow sample)
a struct flow_sample
the number of flow samples (32-bit int, value=2)
The first flow in the first sample:
The flow type as a data_format (int this case a raw packet sample, so...)
the flow data length (32-bit int, value=144)
a struct sampled_header
4 bytes that are skipped as per the value of sampled_header.stripped
ethernet header
IP header (payload=TCP)
TCP header (port=80)
data bytes (62)
The second flow in the first sample:
The flow type as a data_format (int this case extended switch data)
the flow data length (32-bit int, value=16)
a struct extended_switch
Then five more samples. In this case, all the samples contain a raw packet header and extended switch data.
So this should give you a better idea of what you need to do. Since each data packet will be different, you'll need to figure our how many samples you have. Then for each sample, you'll need to figure out the type, and based on that figure out how to parse the individual flows.
If you need more examples I'd strongly suggest using Wireshark to capture these sflow packets so you can see exactly what's in them to validate that your parser works for all expected input.
Related question for reference: use of memcpy to store data from buffer into struct

How to populate binary matrices with all the combinations?

I want to have 2^n matrices with all the combinations of 0 and 1 in them. For example, for n=6 (n=#rows x #columns) array{1}=[0 0 0; 0 0 0],array{2}=[0 0 0; 0 0 1]... array{64}=[1 1 1;1 1 1]. I am using MATLAB and I came across with combn.m (M = COMBN(V,N) returns all combinations of N elements of the elements in vector V. M has the size (length(V).^N)-by-N.), dec2bin() but I can't get it quite right. Another idea of mine was to create a large matrix and then split it into 2^n matrices. For instance,for n=6( 2 x 3), i did this M=combn([0 1],3) which gives me:
M =
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
Then, use this M to create a larger matrix like this M2=combn(M,2), but this produces the wrong results. However, if i concatenate M row like this:
M=combn([000;010;100;001;110;011;101;111],2)' I get something closer to what I expect i.e
M =
Columns 1 through 21
0 0 0 0 0 0 0 0 10 10 10 10 10 10 10 10 100 100 100 100 100
0 10 100 1 110 11 101 111 0 10 100 1 110 11 101 111 0 10 100 1 110
Columns 22 through 42
100 100 100 1 1 1 1 1 1 1 1 110 110 110 110 110 110 110 110 11 11
11 101 111 0 10 100 1 110 11 101 111 0 10 100 1 110 11 101 111 0 10
Columns 43 through 63
11 11 11 11 11 11 101 101 101 101 101 101 101 101 111 111 111 111 111 111 111
100 1 110 11 101 111 0 10 100 1 110 11 101 111 0 10 100 1 110 11 101
Column 64
111
111
where I can get each column and convert it separately into 64 matrices.So, for example column 1 would be converted from [0;0] to [0 0 0;0 0 0] etc. However, i believe it is a much easier problem which it can be solved in less time, elegantly.
Using dec2bin:
r = 2; %// nunber of rows
c = 3; %// number of columns
M = dec2bin(0:2^(r*c)-1)-'0'; %// Or: M = de2bi(0:2^(r*c)-1);
M = reshape(M.',r,c,[]);
M is a 3D-array of size r x c x 2^(r*c), such that M(:,:,1) is the first matrix, M(:,:,2) is the second etc.
How it works:
dec2bin gives a binary string representation of a number. So dec2bin(0:2^(r*c)-1) gives all numbers from 0 to 2^(r*c)-1 expressed in binary, each in one row. The -'0' part just turns the string into a numeric vector of 0 and 1 values. Then reshape puts each of those rows into a r x c form, to make up each of the the desired matrices.

Incorrect output from Fortran loop

I have written a routine to give the column index position for the furthers right cell containing a 1, marking the right edge of a polygon in a mask array.
But when I print the index arrays (I realize the row position array is redundant), all rows are reporting a position (other than 0), which I know shouldn't be the case. I can't seem to find where the following could be incorrect.
Example mask array:
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 0 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 0 0 0
0 0 0 1 1 1 1 1 1 1 1 0 0 0
0 0 0 1 1 1 1 1 1 1 1 0 0 0
0 0 0 0 0 0 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
Desired output:
[0,10,10,11,11,11,9,8,0]
Is this a Fortran thing, or is my logic just off (
Routine:
subroutine get_right_idx(mask_array, idx_x, idx_y)
integer, parameter :: x = 169 ! num columns
integer, parameter :: y = 124 ! num rows
integer i ! iterator for rows
integer j ! iterator for columns
integer row_x ! x position for furthest south cell in row
integer row_y ! y position for furthest south cell in row
integer :: idx_x(y) ! index positions for lowest lat in model grid - x
integer :: idx_y(y) ! index positions for lowest lat in model grid - y
real mask_array(y,x) ! mask array of zeros, containing polygon of ones
do j=1,y
row_x = 0
row_y = 0
do i=1,x
if (mask_array(j,i).eq.1) then
row_x = i
row_y = j
endif
enddo
idx_x(j)=row_x
idx_y(j)=row_y
enddo
endsubroutine get_right_idx
Actual mask (zoomed out in Open Office):
Below is the mask that I am trying to evaluate. My resulting array has a non-zero value in for all elements, where there should be zero elements at the start and end of the array, no matter which direction it is evaluated from.
Output:
125 104 104 104 104 104 104 114 114 114 114 103 103 103 108 108 103 103 103 103 97 97 97 107 107 107 107 107 107 107 107 107 97 101 101 101 101 101 111 111 111 111 111 111 101 101 100 105 105 105 105 105 105 100 115 115 104 104 104 104 104 104 104 104 104 104 98 98 98 98 108 108 108 108 108 108 108 108 98 102 102 102 102 102 112 112 112 112 112 112 101 101 101 106 106 106 101 101 101 95 95 105 105 105 105 105 105 105 105 105 105 99 99 99 99 99 109 109 109 109 109 109 109 99 99
I made a quick template of your code, but with my suggestion. Since you want to find the largest index j that has a 1 in it, you can simply test this by starting your j-loop with the maximum (in the example, 14) and working downwards but exiting the inner do-loop if mask_array==1.
You could generalize this by replacing 14 and 9 with the maximum values for those dimensions.
program get_right
implicit none
integer, dimension(9,14) :: mask_array
integer :: i,j,mask_out(9),j_tmp
mask_array(1,:)=[0,0,0,0,0,0,0,0,0,0,0,0,0,0]
mask_array(2,:)=[0,0,0,0,0,0,0,1,0,0,0,0,0,0]
mask_array(3,:)=[0,0,0,0,0,0,1,1,1,0,0,0,0,0]
mask_array(4,:)=[0,0,0,0,0,1,1,1,1,1,1,0,0,0]
mask_array(5,:)=[0,0,0,1,1,1,1,1,1,1,1,0,0,0]
mask_array(6,:)=[0,0,0,1,1,1,1,1,1,1,1,0,0,0]
mask_array(7,:)=[0,0,0,0,0,0,1,1,1,1,0,0,0,0]
mask_array(8,:)=[0,0,0,0,0,0,0,0,0,1,0,0,0,0]
mask_array(9,:)=[0,0,0,0,0,0,0,0,0,0,0,0,0,0]
mask_out=0
do i=1,9
j_tmp=0
print '(14(i0,2x))',mask_array(i,:)
do j=14,1,-1
if(mask_array(i,j)==1) then
j_tmp=j
exit
endif
enddo
mask_out(i)=j
enddo
print *,""
print '(9(i0,2x))',mask_out
end program get_right
I got 0,8,9,11,11,11,10,10,0 as the answer (which is what you got but backwards).
Or, if typing makes you tired you could evaluate this
maxval(mask_array*spread([(ix,ix=lbound(mask_array,dim=2),&
ubound(mask_array,dim=2))],dim=1, ncopies=size(mask_array,dim=1)),dim=2)
As you can see this makes a temporary array (which may be undesirable if your masks are large) using spread and an implied-do loop, each element of this temporary contains its own column index number. Then it multiplies the temporary with the mask_array, performing element-wise multiplication not matrix multiplication. Finally take the maxval of each row of the result. This returns the vector in the same order as Kyle's code does.
I've edited the code to use lbound and ubound rather than 1 and size in case you want to use the code on arrays with lower bounds other than 1.
Bob's yer uncle, but don't ask whether this is faster than Kyle's code. If you are interested in execution speed test and measure.
Incidentally, since this returns just one vector and doesn't modify its arguments or have any other side effects, I'd package it as a function rather than as a subroutine.

Resources